diff --git a/.golangci.yml b/.golangci.yml
index a5de08e54..be0ed8766 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -199,6 +199,10 @@ linters:
- goheader # checks is file header matches to pattern
- misspell # [useless] finds commonly misspelled English words in comments
+run:
+ skip-dirs:
+ - registry/app/api/controller/mocks
+
issues:
# Maximum count of issues with the same text.
# Set to 0 to disable.
diff --git a/registry/app/api/controller/metadata/base.go b/registry/app/api/controller/metadata/base.go
index ad539382d..5066ca662 100644
--- a/registry/app/api/controller/metadata/base.go
+++ b/registry/app/api/controller/metadata/base.go
@@ -37,23 +37,8 @@ const MediaTypeImageConfig = "application/vnd.docker.container.image.v1+json"
var _ api.StrictServerInterface = (*APIController)(nil)
-type RegistryRequestBaseInfo struct {
- RootIdentifier string
- rootIdentifierID int64
-
- RegistryRef string
- RegistryIdentifier string
- RegistryID int64
-
- ParentRef string
- parentID int64
-
- RegistryType api.RegistryType
- PackageType api.PackageType
-}
-
type RegistryRequestInfo struct {
- RegistryRequestBaseInfo
+ *types.RegistryRequestBaseInfo
packageTypes []string
sortByField string
sortByOrder string
@@ -82,7 +67,7 @@ type RegistryRequestParams struct {
}
type ArtifactFilesRequestInfo struct {
- RegistryRequestBaseInfo
+ *types.RegistryRequestBaseInfo
sortByField string
sortByOrder string
offset int
@@ -138,7 +123,7 @@ func (c *APIController) GetRegistryRequestInfo(
}
return &RegistryRequestInfo{
- RegistryRequestBaseInfo: *baseInfo,
+ RegistryRequestBaseInfo: baseInfo,
packageTypes: packageTypes,
sortByField: sortByField,
sortByOrder: sortByOrder,
@@ -415,7 +400,7 @@ func (c *APIController) GetArtifactFilesRequestInfo(
}
return &ArtifactFilesRequestInfo{
- RegistryRequestBaseInfo: *baseInfo,
+ RegistryRequestBaseInfo: baseInfo,
sortByField: sortByField,
sortByOrder: sortByOrder,
offset: offset,
diff --git a/registry/app/api/controller/metadata/controller.go b/registry/app/api/controller/metadata/controller.go
index 8e34a3683..9506fcc37 100644
--- a/registry/app/api/controller/metadata/controller.go
+++ b/registry/app/api/controller/metadata/controller.go
@@ -16,13 +16,14 @@ package metadata
import (
"github.com/harness/gitness/app/auth/authz"
- "github.com/harness/gitness/app/services/refcache"
urlprovider "github.com/harness/gitness/app/url"
"github.com/harness/gitness/audit"
+ "github.com/harness/gitness/registry/app/api/interfaces"
storagedriver "github.com/harness/gitness/registry/app/driver"
registryevents "github.com/harness/gitness/registry/app/events"
"github.com/harness/gitness/registry/app/pkg/filemanager"
"github.com/harness/gitness/registry/app/store"
+ "github.com/harness/gitness/registry/services/webhook"
"github.com/harness/gitness/store/database/dbtx"
)
@@ -37,7 +38,7 @@ type APIController struct {
TagStore store.TagRepository
ManifestStore store.ManifestRepository
CleanupPolicyStore store.CleanupPolicyRepository
- SpaceFinder SpaceFinder
+ SpaceFinder interfaces.SpaceFinder
tx dbtx.Transactor
StorageDriver storagedriver.StorageDriver
URLProvider urlprovider.Provider
@@ -46,8 +47,8 @@ type APIController struct {
ArtifactStore store.ArtifactRepository
WebhooksRepository store.WebhooksRepository
WebhooksExecutionRepository store.WebhooksExecutionRepository
- RegistryMetadataHelper RegistryMetadataHelper
- WebhookService WebhookService
+ RegistryMetadataHelper interfaces.RegistryMetadataHelper
+ WebhookService webhook.ServiceInterface
ArtifactEventReporter registryevents.Reporter
DownloadStatRepository store.DownloadStatRepository
}
@@ -63,7 +64,7 @@ func NewAPIController(
cleanupPolicyStore store.CleanupPolicyRepository,
imageStore store.ImageRepository,
driver storagedriver.StorageDriver,
- spaceFinder refcache.SpaceFinder,
+ spaceFinder interfaces.SpaceFinder,
tx dbtx.Transactor,
urlProvider urlprovider.Provider,
authorizer authz.Authorizer,
@@ -71,8 +72,8 @@ func NewAPIController(
artifactStore store.ArtifactRepository,
webhooksRepository store.WebhooksRepository,
webhooksExecutionRepository store.WebhooksExecutionRepository,
- registryMetadataHelper RegistryMetadataHelper,
- webhookService WebhookService,
+ registryMetadataHelper interfaces.RegistryMetadataHelper,
+ webhookService webhook.ServiceInterface,
artifactEventReporter registryevents.Reporter,
downloadStatRepository store.DownloadStatRepository,
) *APIController {
diff --git a/registry/app/api/controller/metadata/create_registry.go b/registry/app/api/controller/metadata/create_registry.go
index 14a13bf0b..8c0313873 100644
--- a/registry/app/api/controller/metadata/create_registry.go
+++ b/registry/app/api/controller/metadata/create_registry.go
@@ -79,7 +79,7 @@ func (c *APIController) CreateRegistry(
registry, upstreamproxy, err := c.CreateUpstreamProxyEntity(
ctx,
registryRequest,
- regInfo.parentID, regInfo.rootIdentifierID,
+ regInfo.ParentID, regInfo.RootIdentifierID,
)
var registryID int64
if err != nil {
@@ -127,16 +127,16 @@ func (c *APIController) CreateRegistry(
}
func (c *APIController) createVirtualRegistry(
- ctx context.Context, registryRequest artifact.RegistryRequest, regInfo *RegistryRequestBaseInfo,
+ ctx context.Context, registryRequest artifact.RegistryRequest, regInfo *registrytypes.RegistryRequestBaseInfo,
session *auth.Session, parentRef artifact.SpaceRefPathParam,
) (artifact.CreateRegistryResponseObject, error) {
- registry, err := CreateRegistryEntity(registryRequest, regInfo.parentID, regInfo.rootIdentifierID)
+ registry, err := CreateRegistryEntity(registryRequest, regInfo.ParentID, regInfo.RootIdentifierID)
if err != nil {
return throwCreateRegistry400Error(err), nil
}
if registry.PackageType != artifact.PackageTypeGENERIC {
- err = c.setUpstreamProxyIDs(ctx, registry, registryRequest, regInfo.parentID)
+ err = c.setUpstreamProxyIDs(ctx, registry, registryRequest, regInfo.ParentID)
}
if err != nil {
return throwCreateRegistry400Error(err), nil
@@ -332,7 +332,7 @@ func (c *APIController) CreateUpstreamProxyEntity(
}
if res.SecretSpacePath != nil && len(*res.SecretSpacePath) > 0 {
- upstreamProxyConfigEntity.SecretSpaceID, err = c.RegistryMetadataHelper.getSecretSpaceID(ctx,
+ upstreamProxyConfigEntity.SecretSpaceID, err = c.RegistryMetadataHelper.GetSecretSpaceID(ctx,
res.SecretSpacePath)
if err != nil {
return nil, nil, err
@@ -355,7 +355,7 @@ func (c *APIController) CreateUpstreamProxyEntity(
default:
if res.AccessKeySecretSpacePath != nil && len(*res.AccessKeySecretSpacePath) > 0 {
upstreamProxyConfigEntity.UserNameSecretSpaceID, err =
- c.RegistryMetadataHelper.getSecretSpaceID(ctx, res.AccessKeySecretSpacePath)
+ c.RegistryMetadataHelper.GetSecretSpaceID(ctx, res.AccessKeySecretSpacePath)
if err != nil {
return nil, nil, err
}
@@ -366,7 +366,7 @@ func (c *APIController) CreateUpstreamProxyEntity(
}
if res.SecretKeySpacePath != nil && len(*res.SecretKeySpacePath) > 0 {
- upstreamProxyConfigEntity.SecretSpaceID, err = c.RegistryMetadataHelper.getSecretSpaceID(ctx,
+ upstreamProxyConfigEntity.SecretSpaceID, err = c.RegistryMetadataHelper.GetSecretSpaceID(ctx,
res.SecretKeySpacePath)
if err != nil {
return nil, nil, err
diff --git a/registry/app/api/controller/metadata/create_registry_test.go b/registry/app/api/controller/metadata/create_registry_test.go
new file mode 100644
index 000000000..91976436f
--- /dev/null
+++ b/registry/app/api/controller/metadata/create_registry_test.go
@@ -0,0 +1,483 @@
+// Copyright 2023 Harness, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//nolint:lll,revive // revive:disable:unused-parameter
+
+package metadata_test
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "testing"
+
+ "github.com/harness/gitness/app/api/request"
+ "github.com/harness/gitness/app/auth"
+ "github.com/harness/gitness/audit"
+ "github.com/harness/gitness/events"
+ "github.com/harness/gitness/registry/app/api/controller/metadata"
+ "github.com/harness/gitness/registry/app/api/controller/mocks"
+ api "github.com/harness/gitness/registry/app/api/openapi/contracts/artifact"
+ registryevents "github.com/harness/gitness/registry/app/events"
+ "github.com/harness/gitness/registry/app/pkg/filemanager"
+ "github.com/harness/gitness/registry/types"
+ "github.com/harness/gitness/registry/utils"
+ coretypes "github.com/harness/gitness/types"
+ gitnessenum "github.com/harness/gitness/types/enum"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/mock"
+)
+
+const (
+ // TestRegistryName is the name used for test registries.
+ testRegistryName = "test-registry"
+)
+
+var (
+ // ErrTestConsumerNotNeeded is a sentinel error indicating consumer is not needed in tests.
+ ErrTestConsumerNotNeeded = errors.New("consumer not needed in tests")
+)
+
+func TestCreateRegistry(t *testing.T) {
+ space := &coretypes.SpaceCore{
+ ID: 1,
+ Path: "root",
+ }
+
+ // Create mock event system components.
+ producer := &mocks.StreamProducer{}
+
+ // Set up producer expectations.
+ producer.On("Send", mock.Anything, "registry", mock.MatchedBy(func(payload map[string]interface{}) bool {
+ return payload["action"] == "registry.create" &&
+ payload["registry_id"] == int64(1) &&
+ payload["registry_name"] == testRegistryName
+ })).Return("", nil).Once()
+
+ // Create events system.
+ consumerFactory := func(_ string, _ string) (events.StreamConsumer, error) {
+ // Return a sentinel error to indicate consumer is not needed in tests.
+ return nil, ErrTestConsumerNotNeeded
+ }
+ eventsSystem, err := events.NewSystem(consumerFactory, producer)
+ if err != nil {
+ t.Fatalf("Failed to create events system: %v", err)
+ }
+
+ // Create event reporter.
+ reporter, err := registryevents.NewReporter(eventsSystem)
+ if err != nil {
+ t.Fatalf("Failed to create event reporter: %v", err)
+ }
+ eventReporter := *reporter // Use value instead of pointer.
+
+ // Helper mocks and setup complete.
+
+ tests := []struct {
+ name string
+ request api.CreateRegistryRequestObject
+ setupMocks func() *metadata.APIController
+ expectedResp interface{}
+ }{
+ {
+ name: "create_virtual_registry_success",
+ request: api.CreateRegistryRequestObject{
+ Body: &api.CreateRegistryJSONRequestBody{
+ Identifier: testRegistryName,
+ ParentRef: utils.StringPtr("root"),
+ Config: func() *api.RegistryConfig {
+ config := &api.RegistryConfig{Type: api.RegistryTypeVIRTUAL}
+ _ = config.FromVirtualConfig(api.VirtualConfig{UpstreamProxies: &[]string{}})
+ return config
+ }(),
+ PackageType: api.PackageTypeDOCKER,
+ CleanupPolicy: &[]api.CleanupPolicy{},
+ },
+ },
+ expectedResp: api.CreateRegistry201JSONResponse{
+ RegistryResponseJSONResponse: api.RegistryResponseJSONResponse{
+ Data: api.Registry{
+ Identifier: testRegistryName,
+ Config: &api.RegistryConfig{
+ Type: api.RegistryTypeVIRTUAL,
+ },
+ PackageType: api.PackageTypeDOCKER,
+ Url: "http://example.com/registry/test-registry",
+ Description: utils.StringPtr(""),
+ CreatedAt: utils.StringPtr("-62135596800000"),
+ ModifiedAt: utils.StringPtr("-62135596800000"),
+ },
+ Status: api.StatusSUCCESS,
+ },
+ },
+ setupMocks: func() *metadata.APIController {
+ mockRegistryMetadataHelper := new(mocks.RegistryMetadataHelper)
+ mockRegistryRepo := new(mocks.RegistryRepository)
+ mockSpaceFinder := new(mocks.SpaceFinder)
+ mockAuthorizer := new(mocks.Authorizer)
+ mockAuditService := new(mocks.AuditService)
+ mockCleanupPolicyRepo := new(mocks.CleanupPolicyRepository)
+ mockTransactor := new(mocks.Transactor)
+ mockGenericBlobRepo := new(mocks.GenericBlobRepository)
+ // Create a mock URL provider.
+ mockURLProvider := new(mocks.Provider)
+ // Set up common URL provider expectations
+ mockURLProvider.On("PackageURL", mock.Anything, mock.Anything, mock.Anything,
+ mock.Anything).Return("http://example.com/registry/test-registry/docker")
+ mockURLProvider.On("GenerateUIRegistryURL", mock.Anything, mock.Anything,
+ mock.Anything).Return("http://example.com/registry/test-registry")
+ mockURLProvider.On("RegistryURL", mock.Anything, mock.Anything,
+ mock.Anything).Return("http://example.com/registry/test-registry")
+
+ // Setup base info mock.
+ baseInfo := &types.RegistryRequestBaseInfo{
+ RegistryID: 1,
+ RegistryIdentifier: testRegistryName,
+ ParentRef: "root",
+ ParentID: 2,
+ RootIdentifierID: 3,
+ RootIdentifier: "root",
+ RegistryType: api.RegistryTypeVIRTUAL,
+ PackageType: api.PackageTypeDOCKER,
+ }
+ // Create the registry entity that will be used in mocks.
+ registry := &types.Registry{
+ ID: baseInfo.RegistryID,
+ Name: testRegistryName,
+ ParentID: baseInfo.ParentID,
+ RootParentID: baseInfo.RootIdentifierID,
+ Type: api.RegistryTypeVIRTUAL,
+ PackageType: api.PackageTypeDOCKER,
+ }
+
+ // 1. Mock the initial registry metadata lookup.
+ mockRegistryMetadataHelper.On("GetRegistryRequestBaseInfo", mock.Anything, "root", "").Return(baseInfo, nil).Once()
+
+ // 2. Mock the space lookup.
+ mockSpaceFinder.On("FindByRef", mock.Anything, "root").Return(space, nil).Once()
+
+ // 3. Mock the authorization check.
+ mockAuthorizer.On("Check", mock.Anything, mock.Anything,
+ mock.MatchedBy(func(scope *coretypes.Scope) bool { return scope.SpacePath == "root" }),
+ mock.MatchedBy(func(r *coretypes.Resource) bool { return r.Type == gitnessenum.ResourceTypeRegistry }),
+ gitnessenum.PermissionRegistryEdit).Return(true, nil).Once()
+
+ // 4. Mock registry creation
+ mockRegistryRepo.On("Create", mock.Anything,
+ mock.MatchedBy(func(r *types.Registry) bool {
+ return r.Name == testRegistryName &&
+ r.ParentID == baseInfo.ParentID &&
+ r.Type == api.RegistryTypeVIRTUAL &&
+ r.PackageType == api.PackageTypeDOCKER
+ })).Return(baseInfo.RegistryID, nil).Once()
+
+ // 5. Mock registry retrieval.
+ mockRegistryRepo.On("Get", mock.Anything, baseInfo.RegistryID).Return(registry, nil).Once()
+
+ // 6. Mock cleanup policy retrieval.
+ mockCleanupPolicyRepo.On("GetByRegistryID", mock.Anything,
+ baseInfo.RegistryID).Return(&[]types.CleanupPolicy{}, nil).Once()
+
+ // URL provider mock expectations set up above
+
+ // Mock setup already done above.
+
+ // Setup already covered above.
+
+ // Create file manager.
+ var app = &filemanager.App{
+ Context: context.Background(),
+ }
+ fileManager := filemanager.NewFileManager(
+ app,
+ mockRegistryRepo,
+ mockGenericBlobRepo,
+ nil, // nodesRepo - not needed for this test.
+ mockTransactor,
+ nil, // reporter - not needed for this test.
+ )
+
+ // Setup audit service mock.
+ mockAuditService.On("Log", mock.Anything,
+ mock.MatchedBy(func(p coretypes.Principal) bool { return p.ID == 1 && p.Type == "user" }),
+ mock.MatchedBy(func(r audit.Resource) bool {
+ return r.Type == audit.ResourceTypeRegistry && r.Identifier == testRegistryName
+ }),
+ audit.ActionCreated,
+ "root",
+ mock.Anything,
+ ).Return(nil).Once()
+
+ // Setup registry repo mock.
+ mockRegistryRepo.On("FetchUpstreamProxyKeys", mock.Anything, mock.Anything).Return([]string{}, nil).Once()
+ mockCleanupPolicyRepo.On("GetByRegistryID", mock.Anything,
+ baseInfo.RegistryID).Return(&[]types.CleanupPolicy{}, nil).Once()
+
+ // Authorizer mock already setup above.
+
+ // Create controller.
+ // Setup transactor mock.
+ mockTransactor.On("WithTx", mock.Anything,
+ mock.AnythingOfType("func(context.Context) error"), mock.Anything).Run(func(args mock.Arguments) {
+ // Execute the transaction function.
+ txFn, ok := args.Get(1).(func(context.Context) error)
+ assert.True(t, ok, "Transaction function conversion failed")
+ err := txFn(context.Background())
+ // Check if an error occurs during transaction execution.
+ assert.NoError(t, err, "Transaction function should not return an error")
+ }).Return(nil)
+
+ // Create controller.
+ return metadata.NewAPIController(
+ mockRegistryRepo,
+ fileManager,
+ nil, // blobStore.
+ nil, // genericBlobStore.
+ nil, // upstreamProxyStore.
+ nil, // tagStore.
+ nil, // manifestStore.
+ mockCleanupPolicyRepo,
+ nil, // imageStore.
+ nil, // driver.
+ mockSpaceFinder,
+ mockTransactor,
+ mockURLProvider,
+ mockAuthorizer,
+ mockAuditService,
+ nil, // artifactStore.
+ nil, // webhooksRepository.
+ nil, // webhooksExecutionRepository.
+ mockRegistryMetadataHelper,
+ nil, // webhookService.
+ eventReporter,
+ nil, // downloadStatRepository.
+ )
+ },
+ },
+ {
+ name: "create_registry_invalid_parent",
+ request: api.CreateRegistryRequestObject{
+ Body: &api.CreateRegistryJSONRequestBody{
+ Identifier: testRegistryName,
+ ParentRef: utils.StringPtr("invalid"),
+ Config: func() *api.RegistryConfig {
+ config := &api.RegistryConfig{Type: api.RegistryTypeVIRTUAL}
+ _ = config.FromVirtualConfig(api.VirtualConfig{UpstreamProxies: &[]string{}})
+ return config
+ }(),
+ PackageType: api.PackageTypeDOCKER,
+ CleanupPolicy: &[]api.CleanupPolicy{},
+ },
+ },
+ expectedResp: api.CreateRegistry400JSONResponse{
+ BadRequestJSONResponse: api.BadRequestJSONResponse{
+ Code: "400",
+ Message: "space not found",
+ },
+ },
+ setupMocks: func() *metadata.APIController {
+ mockRegistryMetadataHelper := new(mocks.RegistryMetadataHelper)
+ mockRegistryRepo := new(mocks.RegistryRepository)
+ mockTransactor := new(mocks.Transactor)
+ mockGenericBlobRepo := new(mocks.GenericBlobRepository)
+
+ // Setup error case mock.
+ mockRegistryMetadataHelper.On("GetRegistryRequestBaseInfo", mock.Anything, "invalid", "").
+ Return(nil, fmt.Errorf("space not found")).Once()
+
+ app := &filemanager.App{
+ Context: context.Background(),
+ }
+
+ fileManager := filemanager.NewFileManager(
+ app,
+ mockRegistryRepo,
+ mockGenericBlobRepo,
+ nil, // nodesRepo - not needed for this test.
+ mockTransactor,
+ nil, // reporter - not needed for this test.
+ )
+
+ return metadata.NewAPIController(
+ mockRegistryRepo,
+ fileManager,
+ nil, // blobStore.
+ nil, // genericBlobStore.
+ nil, // upstreamProxyStore.
+ nil, // tagStore.
+ nil, // manifestStore.
+ nil, // cleanupPolicyStore
+ nil, // imageStore.
+ nil, // driver.
+ nil, // spaceFinder
+ mockTransactor,
+ nil, // urlProvider.
+ nil, // authorizer.
+ nil, // auditService.
+ nil, // artifactStore.
+ nil, // webhooksRepository.
+ nil, // webhooksExecutionRepository.
+ mockRegistryMetadataHelper,
+ nil, // webhookService.
+ eventReporter,
+ nil, // downloadStatRepository.
+ )
+ },
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ // Create the controller.
+ controller := tt.setupMocks()
+
+ // Create context with auth session.
+ ctx := context.Background()
+ session := &auth.Session{
+ Principal: coretypes.Principal{
+ ID: 1,
+ Type: "user",
+ },
+ }
+ ctx = request.WithAuthSession(ctx, session)
+
+ // Call the API.
+ registryResp, err := controller.CreateRegistry(ctx, tt.request)
+
+ // Verify response matches expected type and content.
+ switch expected := tt.expectedResp.(type) {
+ case api.CreateRegistry201JSONResponse:
+ assert.NoError(t, err, "Expected no error but got one")
+ actualResp, ok := registryResp.(api.CreateRegistry201JSONResponse)
+ assert.True(t, ok, "Expected 201 response")
+ assert.Equal(t, expected.Status, actualResp.Status, "Response status should match")
+
+ // Verify registry data fields individually.
+ assert.Equal(t, expected.Data.Identifier, actualResp.Data.Identifier, "Registry identifier should match")
+ assert.Equal(t, expected.Data.PackageType, actualResp.Data.PackageType, "Package type should match")
+ assert.Equal(t, expected.Data.Url, actualResp.Data.Url, "Registry URL should match")
+ assert.Equal(t, expected.Data.Description, actualResp.Data.Description, "Description should match")
+ assert.Equal(t, expected.Data.CreatedAt, actualResp.Data.CreatedAt, "CreatedAt should match")
+ assert.Equal(t, expected.Data.ModifiedAt, actualResp.Data.ModifiedAt, "ModifiedAt should match")
+
+ // Verify config type.
+ assert.NotNil(t, actualResp.Data.Config, "Config should not be nil")
+ assert.Equal(t, expected.Data.Config.Type, actualResp.Data.Config.Type, "Config type should match")
+
+ // Verify mock expectations for success case.
+ called := controller.RegistryRepository.(*mocks.RegistryRepository).AssertCalled(t, "Create", //nolint:errcheck
+ mock.Anything, mock.MatchedBy(func(r *types.Registry) bool {
+ return r.Name == tt.request.Body.Identifier &&
+ r.Type == tt.request.Body.Config.Type &&
+ r.PackageType == tt.request.Body.PackageType
+ }))
+ assert.True(t, called, "Expected Create call not made")
+
+ // Verify all mocks expectations were met.
+ mockRegistry, regOk := controller.RegistryRepository.(*mocks.RegistryRepository)
+ assert.True(t, regOk, "Type assertion to RegistryRepository failed")
+ regAssertOk := mockRegistry.AssertExpectations(t)
+ assert.True(t, regAssertOk, "Mock expectations failed for RegistryRepository")
+
+ mockAudit, auditOk := controller.AuditService.(*mocks.AuditService)
+ assert.True(t, auditOk, "Type assertion to AuditService failed")
+ auditAssertOk := mockAudit.AssertExpectations(t)
+ assert.True(t, auditAssertOk, "Mock expectations failed for AuditService")
+
+ // Verify audit expectations.
+ logCalled := controller.AuditService.(*mocks.AuditService).AssertCalled(t, "Log", mock.Anything, //nolint:errcheck
+ mock.Anything, mock.Anything, audit.ActionCreated, mock.Anything, mock.Anything)
+ assert.True(t, logCalled, "Expected Log call not made")
+
+ case api.CreateRegistry400JSONResponse:
+ assert.Error(t, err, "Expected an error")
+ actualResp, ok := registryResp.(api.CreateRegistry400JSONResponse)
+ assert.True(t, ok, "Expected 400 response")
+ assert.Equal(t, expected.Code, actualResp.Code, "Error code should match")
+ assert.Equal(t, expected.Message, actualResp.Message, "Error message should match")
+
+ // Additional assertions for specific error cases.
+ switch tt.name {
+ case "create_registry_invalid_parent":
+ assert.Contains(t, actualResp.Message, "space not found",
+ "Error message should indicate invalid parent")
+ notCalled := controller.RegistryRepository.(*mocks.RegistryRepository).AssertNotCalled(t, //nolint:errcheck
+ "Create", mock.Anything, mock.Anything)
+ assert.True(t, notCalled, "Unexpected Create call made")
+
+ // Verify expectations for the error case.
+ metaHelper, metaHelperOk := controller.RegistryMetadataHelper.(*mocks.RegistryMetadataHelper)
+ assert.True(t, metaHelperOk, "Type assertion to RegistryMetadataHelper failed")
+ assertMetaOk := metaHelper.AssertExpectations(t)
+ assert.True(t, assertMetaOk, "Mock expectations failed for RegistryMetadataHelper")
+ case "create_registry_duplicate":
+ assert.Contains(t, actualResp.Message, "already defined",
+ "Error message should indicate duplicate registry")
+ assert.Contains(t, actualResp.Message, tt.request.Body.Identifier,
+ "Error message should include the registry identifier")
+ getByNameCalled := controller.RegistryRepository.(*mocks.RegistryRepository).AssertCalled(t, //nolint:errcheck
+ "GetByRootParentIDAndName", mock.Anything, mock.Anything, tt.request.Body.Identifier)
+ assert.True(t, getByNameCalled, "Expected GetByRootParentIDAndName call not made")
+ }
+
+ case api.CreateRegistry403JSONResponse:
+ assert.Error(t, err, "Expected an error")
+ actualResp, ok := registryResp.(api.CreateRegistry403JSONResponse)
+ assert.True(t, ok, "Expected 403 response")
+ assert.Equal(t, expected.Code, actualResp.Code, "Error code should match")
+ assert.Equal(t, expected.Message, actualResp.Message, "Error message should match")
+ assert.Contains(t, actualResp.Message, "unauthorized",
+ "Error message should indicate authorization failure")
+ _ = controller.RegistryRepository.(*mocks.RegistryRepository).AssertNotCalled(t, //nolint:errcheck
+ "Create", mock.Anything, mock.Anything)
+
+ default:
+ t.Fatalf("Unexpected response type: %T", tt.expectedResp)
+ }
+
+ // Verify common mock expectations.
+ if controller.RegistryRepository != nil {
+ registryRepo, regOk := controller.RegistryRepository.(*mocks.RegistryRepository)
+ assert.True(t, regOk, "Type assertion to RegistryRepository failed")
+ assertRegOk := registryRepo.AssertExpectations(t)
+ assert.True(t, assertRegOk, "Mock expectations failed for RegistryRepository")
+ }
+ if controller.RegistryMetadataHelper != nil {
+ metaHelper, metaHelperOk := controller.RegistryMetadataHelper.(*mocks.RegistryMetadataHelper)
+ assert.True(t, metaHelperOk, "Type assertion to RegistryMetadataHelper failed")
+ assertMetaOk := metaHelper.AssertExpectations(t)
+ assert.True(t, assertMetaOk, "Mock expectations failed for RegistryMetadataHelper")
+ }
+ if controller.SpaceFinder != nil {
+ spaceFinder, finderOk := controller.SpaceFinder.(*mocks.SpaceFinder)
+ assert.True(t, finderOk, "Type assertion to SpaceFinder failed")
+ spaceFinderOk := spaceFinder.AssertExpectations(t)
+ assert.True(t, spaceFinderOk, "Mock expectations failed for SpaceFinder")
+ }
+ if controller.Authorizer != nil {
+ auth, authOk := controller.Authorizer.(*mocks.Authorizer)
+ assert.True(t, authOk, "Type assertion to Authorizer failed")
+ authAssertOk := auth.AssertExpectations(t)
+ assert.True(t, authAssertOk, "Mock expectations failed for Authorizer")
+ }
+ if controller.AuditService != nil {
+ auditSvc, auditSvcOk := controller.AuditService.(*mocks.AuditService)
+ assert.True(t, auditSvcOk, "Type assertion to AuditService failed")
+ auditSvcAssertOk := auditSvc.AssertExpectations(t)
+ assert.True(t, auditSvcAssertOk, "Mock expectations failed for AuditService")
+ }
+ })
+ }
+}
diff --git a/registry/app/api/controller/metadata/create_webhook.go b/registry/app/api/controller/metadata/create_webhook.go
index ef94e0739..140f6116f 100644
--- a/registry/app/api/controller/metadata/create_webhook.go
+++ b/registry/app/api/controller/metadata/create_webhook.go
@@ -72,13 +72,14 @@ func (c *APIController) CreateWebhook(
}
webhook, err := c.RegistryMetadataHelper.MapToWebhookCore(ctx, webhookRequest, regInfo)
- webhook.Type = enum.WebhookTypeExternal
- webhook.CreatedBy = session.Principal.ID
if err != nil {
log.Ctx(ctx).Error().Msgf("failed to store webhook: %s with error: %v", webhookRequest.Identifier, err)
return createWebhookBadRequestErrorResponse(fmt.Errorf("failed to store webhook %w", err))
}
+ webhook.Type = enum.WebhookTypeExternal
+ webhook.CreatedBy = session.Principal.ID
+
err = c.WebhooksRepository.Create(ctx, webhook)
if err != nil {
log.Ctx(ctx).Error().Msgf("failed to store webhook: %s with error: %v", webhookRequest.Identifier, err)
diff --git a/registry/app/api/controller/metadata/create_webhook_test.go b/registry/app/api/controller/metadata/create_webhook_test.go
new file mode 100644
index 000000000..6c4116e32
--- /dev/null
+++ b/registry/app/api/controller/metadata/create_webhook_test.go
@@ -0,0 +1,556 @@
+// Copyright 2023 Harness, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//nolint:lll,revive // revive:disable:unused-parameter
+package metadata_test
+
+import (
+ "context"
+ "fmt"
+ "testing"
+
+ apiauth "github.com/harness/gitness/app/api/auth"
+ "github.com/harness/gitness/app/api/request"
+ "github.com/harness/gitness/app/auth"
+ "github.com/harness/gitness/registry/app/api/controller/metadata"
+ "github.com/harness/gitness/registry/app/api/controller/mocks"
+ api "github.com/harness/gitness/registry/app/api/openapi/contracts/artifact"
+ registrytypes "github.com/harness/gitness/registry/types"
+ "github.com/harness/gitness/registry/utils"
+ coretypes "github.com/harness/gitness/types"
+ "github.com/harness/gitness/types/enum"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/mock"
+)
+
+const (
+ testWebhookIdentifier = "test-webhook"
+ testWebhookURL = "http://example.com"
+)
+
+func TestCreateWebhook(t *testing.T) {
+ tests := []struct {
+ name string
+ setupMocks func(*metadata.APIController)
+ request api.CreateWebhookRequestObject
+ expectedResp interface{}
+ expectedError error
+ }{
+ {
+ name: "success_case",
+ setupMocks: func(c *metadata.APIController) {
+ // Mock registry metadata helper
+ mockRegistryMetadataHelper := new(mocks.RegistryMetadataHelper)
+ mockSpaceFinder := new(mocks.SpaceFinder)
+ mockWebhooksRepository := new(mocks.WebhooksRepository)
+ mockAuthorizer := new(mocks.Authorizer)
+
+ regInfo := ®istrytypes.RegistryRequestBaseInfo{
+ RegistryID: 1,
+ RegistryIdentifier: "reg",
+ ParentID: 2,
+ ParentRef: "root/parent",
+ RegistryType: api.RegistryTypeVIRTUAL,
+ }
+
+ space := &coretypes.SpaceCore{
+ Path: "root/parent",
+ }
+
+ permissionChecks := []coretypes.PermissionCheck{
+ {
+ Scope: coretypes.Scope{SpacePath: "root/parent"},
+ Resource: coretypes.Resource{
+ Type: enum.ResourceTypeRegistry,
+ Identifier: "reg",
+ },
+ Permission: enum.PermissionRegistryEdit,
+ },
+ }
+
+ webhook := &coretypes.WebhookCore{
+ ID: 1,
+ DisplayName: testWebhookIdentifier,
+ Identifier: testWebhookIdentifier,
+ URL: "http://example.com",
+ Enabled: true,
+ Insecure: false,
+ ParentID: regInfo.RegistryID,
+ Type: enum.WebhookTypeExternal,
+ }
+
+ webhookResponseEntity := &api.Webhook{
+ Identifier: "test-webhook",
+ Name: testWebhookIdentifier,
+ Url: "http://example.com",
+ Enabled: true,
+ Insecure: false,
+ CreatedAt: utils.StringPtr("2023-01-01T00:00:00Z"),
+ ModifiedAt: utils.StringPtr("2023-01-01T00:00:00Z"),
+ }
+
+ // Set up expectations.
+ mockSpaceFinder.On("FindByRef", mock.Anything, "root/parent").Return(space, nil)
+ mockRegistryMetadataHelper.On("GetRegistryRequestBaseInfo", mock.Anything, "", "reg").Return(regInfo, nil)
+ mockRegistryMetadataHelper.On(
+ "GetPermissionChecks",
+ mock.Anything,
+ "reg",
+ enum.PermissionRegistryEdit,
+ ).Return(permissionChecks)
+ // Set up authorizer to expect a session with Principal ID 123 for success case
+ mockSession := &auth.Session{Principal: coretypes.Principal{ID: 123}}
+ mockAuthorizer.On("CheckAll", mock.Anything, mockSession, permissionChecks[0]).Return(true, nil)
+
+ mockRegistryMetadataHelper.On(
+ "MapToWebhookCore",
+ mock.Anything,
+ mock.MatchedBy(func(req api.WebhookRequest) bool {
+ return req.Identifier == testWebhookIdentifier &&
+ req.Name == testWebhookIdentifier &&
+ req.Url == testWebhookURL &&
+ req.Enabled == true &&
+ req.Insecure == false
+ }),
+ regInfo,
+ ).Return(webhook, nil)
+
+ mockWebhooksRepository.On("Create", mock.Anything, webhook).Return(nil)
+ mockWebhooksRepository.On(
+ "GetByRegistryAndIdentifier",
+ mock.Anything,
+ regInfo.RegistryID,
+ "test-webhook",
+ ).Return(webhook, nil)
+ mockRegistryMetadataHelper.On(
+ "MapToWebhookResponseEntity",
+ mock.Anything,
+ webhook,
+ ).Return(webhookResponseEntity, nil)
+
+ // Assign mocks to controller
+ c.SpaceFinder = mockSpaceFinder
+ c.RegistryMetadataHelper = mockRegistryMetadataHelper
+ c.Authorizer = mockAuthorizer
+ c.WebhooksRepository = mockWebhooksRepository
+ },
+ request: api.CreateWebhookRequestObject{
+ RegistryRef: "reg",
+ Body: &api.CreateWebhookJSONRequestBody{
+ Name: testWebhookIdentifier,
+ Identifier: testWebhookIdentifier,
+ Url: "http://example.com",
+ Enabled: true,
+ Insecure: false,
+ },
+ },
+ expectedResp: api.CreateWebhook201JSONResponse{
+ WebhookResponseJSONResponse: api.WebhookResponseJSONResponse{
+ Data: api.Webhook{
+ Name: "test-webhook",
+ Identifier: "test-webhook",
+ Url: "http://example.com",
+ Enabled: true,
+ Insecure: false,
+ },
+ Status: api.StatusSUCCESS,
+ },
+ },
+ },
+ {
+ name: "reserved_identifier",
+ setupMocks: func(c *metadata.APIController) {
+ // 1. Mock registry metadata helper for GetRegistryRequestBaseInfo
+ mockRegistryMetadataHelper := new(mocks.RegistryMetadataHelper)
+ regInfo := ®istrytypes.RegistryRequestBaseInfo{
+ RegistryID: 1,
+ RegistryIdentifier: "reg",
+ ParentID: 2,
+ ParentRef: "root/parent",
+ RegistryType: api.RegistryTypeVIRTUAL,
+ }
+ mockRegistryMetadataHelper.On("GetRegistryRequestBaseInfo", mock.Anything, "", "reg").
+ Return(regInfo, nil)
+ c.RegistryMetadataHelper = mockRegistryMetadataHelper
+
+ // 2. Mock SpaceFinder
+ mockSpaceFinder := new(mocks.SpaceFinder)
+ space := &coretypes.SpaceCore{
+ Path: "root/parent",
+ }
+ mockSpaceFinder.On("FindByRef", mock.Anything, "root/parent").Return(space, nil)
+ c.SpaceFinder = mockSpaceFinder
+
+ // 3. Mock GetPermissionChecks
+ permissionCheck := coretypes.PermissionCheck{
+ Scope: coretypes.Scope{SpacePath: "root/parent"},
+ Resource: coretypes.Resource{
+ Type: enum.ResourceTypeRegistry,
+ Identifier: "reg",
+ },
+ Permission: enum.PermissionRegistryEdit,
+ }
+ mockRegistryMetadataHelper.On("GetPermissionChecks", mock.Anything, "reg", enum.PermissionRegistryEdit).
+ Return([]coretypes.PermissionCheck{permissionCheck})
+
+ // 4. Mock Authorizer
+ mockAuthorizer := new(mocks.Authorizer)
+ mockAuthorizer.On("CheckAll", mock.Anything, (*auth.Session)(nil), permissionCheck).Return(true, nil)
+ c.Authorizer = mockAuthorizer
+
+ // 5. Mock MapToWebhookCore
+ mockRegistryMetadataHelper.On("MapToWebhookCore", mock.Anything,
+ mock.MatchedBy(func(req api.WebhookRequest) bool {
+ return req.Identifier == "internal-webhook" &&
+ req.Name == "internal-webhook" &&
+ req.Url == testWebhookURL &&
+ req.Enabled == true &&
+ req.Insecure == false
+ }), regInfo).Return(nil, fmt.Errorf("webhook identifier internal-webhook is reserved"))
+ },
+ request: api.CreateWebhookRequestObject{
+ RegistryRef: "reg",
+ Body: &api.CreateWebhookJSONRequestBody{
+ Name: "internal-webhook",
+ Identifier: "internal-webhook",
+ Url: "http://example.com",
+ Enabled: true,
+ Insecure: false,
+ },
+ },
+ expectedResp: api.CreateWebhook400JSONResponse{
+ BadRequestJSONResponse: api.BadRequestJSONResponse{
+ Code: "400",
+ Message: "failed to store webhook webhook identifier internal-webhook is reserved",
+ },
+ },
+ },
+ {
+ name: "invalid_registry_reference",
+ setupMocks: func(c *metadata.APIController) {
+ mockRegistryMetadataHelper := new(mocks.RegistryMetadataHelper)
+ mockRegistryMetadataHelper.On("GetRegistryRequestBaseInfo", mock.Anything, "", "invalid-reg").
+ Return(nil, fmt.Errorf("invalid registry reference"))
+ c.RegistryMetadataHelper = mockRegistryMetadataHelper
+ },
+ request: api.CreateWebhookRequestObject{
+ RegistryRef: "invalid-reg",
+ Body: &api.CreateWebhookJSONRequestBody{
+ Name: "test-webhook",
+ Identifier: "test-webhook",
+ Url: "http://example.com",
+ Enabled: true,
+ Insecure: false,
+ },
+ },
+ expectedResp: api.CreateWebhook400JSONResponse{
+ BadRequestJSONResponse: api.BadRequestJSONResponse{
+ Code: "400",
+ Message: "invalid registry reference",
+ },
+ },
+ },
+ {
+ name: "permission_check_fails",
+ setupMocks: func(c *metadata.APIController) {
+ // 1. Mock registry metadata helper for GetRegistryRequestBaseInfo
+ mockRegistryMetadataHelper := new(mocks.RegistryMetadataHelper)
+ regInfo := ®istrytypes.RegistryRequestBaseInfo{
+ RegistryID: 1,
+ RegistryIdentifier: "reg",
+ ParentID: 2,
+ ParentRef: "root/parent",
+ RegistryType: api.RegistryTypeVIRTUAL,
+ }
+ mockRegistryMetadataHelper.On("GetRegistryRequestBaseInfo", mock.Anything, "", "reg").
+ Return(regInfo, nil)
+
+ // 2. Mock SpaceFinder
+ mockSpaceFinder := new(mocks.SpaceFinder)
+ space := &coretypes.SpaceCore{
+ Path: "root/parent",
+ }
+ mockSpaceFinder.On("FindByRef", mock.Anything, "root/parent").Return(space, nil)
+ c.SpaceFinder = mockSpaceFinder
+
+ // 3. Mock GetPermissionChecks
+ permissionCheck := coretypes.PermissionCheck{
+ Scope: coretypes.Scope{SpacePath: "root/parent"},
+ Resource: coretypes.Resource{
+ Type: enum.ResourceTypeRegistry,
+ Identifier: "reg",
+ },
+ Permission: enum.PermissionRegistryEdit,
+ }
+ mockRegistryMetadataHelper.On("GetPermissionChecks", mock.Anything, "reg", enum.PermissionRegistryEdit).
+ Return([]coretypes.PermissionCheck{permissionCheck})
+ c.RegistryMetadataHelper = mockRegistryMetadataHelper
+
+ // Mock authorizer with manual response
+ mockAuthorizer := new(mocks.Authorizer)
+ mockAuthorizer.On("CheckAll", mock.Anything, (*auth.Session)(nil), permissionCheck).Return(false, apiauth.ErrUnauthorized)
+ c.Authorizer = mockAuthorizer
+ },
+ request: api.CreateWebhookRequestObject{
+ RegistryRef: "reg",
+ Body: &api.CreateWebhookJSONRequestBody{
+ Name: testWebhookIdentifier,
+ Identifier: testWebhookIdentifier,
+ Url: "http://example.com",
+ Enabled: true,
+ Insecure: false,
+ },
+ },
+ expectedResp: api.CreateWebhook403JSONResponse{
+ UnauthorizedJSONResponse: api.UnauthorizedJSONResponse{
+ Code: "403",
+ Message: "unauthorized",
+ },
+ },
+ },
+ {
+ name: "non_virtual_registry",
+ setupMocks: func(c *metadata.APIController) {
+ // 1. Mock registry metadata helper for GetRegistryRequestBaseInfo
+ mockRegistryMetadataHelper := new(mocks.RegistryMetadataHelper)
+ regInfo := ®istrytypes.RegistryRequestBaseInfo{
+ RegistryID: 1,
+ RegistryIdentifier: "reg",
+ ParentID: 2,
+ ParentRef: "root/parent",
+ RegistryType: api.RegistryTypeUPSTREAM,
+ }
+ mockRegistryMetadataHelper.On("GetRegistryRequestBaseInfo", mock.Anything, "", "reg").
+ Return(regInfo, nil)
+ c.RegistryMetadataHelper = mockRegistryMetadataHelper
+ },
+ request: api.CreateWebhookRequestObject{
+ RegistryRef: "reg",
+ Body: &api.CreateWebhookJSONRequestBody{
+ Name: testWebhookIdentifier,
+ Identifier: testWebhookIdentifier,
+ Url: "http://example.com",
+ Enabled: true,
+ Insecure: false,
+ },
+ },
+ expectedResp: api.CreateWebhook400JSONResponse{
+ BadRequestJSONResponse: api.BadRequestJSONResponse{
+ Code: "400",
+ Message: "not allowed to create webhook for UPSTREAM registry",
+ },
+ },
+ },
+ {
+ name: "permission_check_fails",
+ setupMocks: func(c *metadata.APIController) {
+ mockSpaceFinder := new(mocks.SpaceFinder)
+ mockRegistryMetadataHelper := new(mocks.RegistryMetadataHelper)
+ mockAuthorizer := new(mocks.Authorizer)
+
+ space := &coretypes.SpaceCore{ID: 2}
+ regInfo := ®istrytypes.RegistryRequestBaseInfo{
+ RegistryID: 1,
+ RegistryIdentifier: "reg",
+ ParentID: 2,
+ ParentRef: "root/parent",
+ RegistryType: api.RegistryTypeVIRTUAL,
+ }
+
+ permissionChecks := []coretypes.PermissionCheck{
+ {
+ Scope: coretypes.Scope{SpacePath: "root/parent"},
+ Resource: coretypes.Resource{Type: enum.ResourceTypeRegistry, Identifier: "reg"},
+ Permission: enum.PermissionRegistryEdit,
+ },
+ }
+
+ mockSpaceFinder.On("FindByRef", mock.Anything, "root/parent").
+ Return(space, nil)
+ mockRegistryMetadataHelper.On("GetRegistryRequestBaseInfo", mock.Anything, "", "reg").
+ Return(regInfo, nil)
+ mockRegistryMetadataHelper.On("GetPermissionChecks", space, "reg", enum.PermissionRegistryEdit).
+ Return(permissionChecks)
+ mockAuthorizer.On("CheckAll", mock.Anything, (*auth.Session)(nil), permissionChecks[0]).
+ Return(false, fmt.Errorf("unauthorized"))
+
+ c.SpaceFinder = mockSpaceFinder
+ c.RegistryMetadataHelper = mockRegistryMetadataHelper
+ c.Authorizer = mockAuthorizer
+ },
+ request: api.CreateWebhookRequestObject{
+ RegistryRef: "reg",
+ Body: &api.CreateWebhookJSONRequestBody{
+ Name: testWebhookIdentifier,
+ Identifier: testWebhookIdentifier,
+ Url: "http://example.com",
+ Enabled: true,
+ Insecure: false,
+ },
+ },
+ expectedResp: api.CreateWebhook403JSONResponse{
+ UnauthorizedJSONResponse: api.UnauthorizedJSONResponse{
+ Code: "403",
+ Message: "unauthorized",
+ },
+ },
+ },
+ {
+ name: "duplicate_webhook_identifier",
+ setupMocks: func(c *metadata.APIController) {
+ mockSpaceFinder := new(mocks.SpaceFinder)
+ mockRegistryMetadataHelper := new(mocks.RegistryMetadataHelper)
+ mockAuthorizer := new(mocks.Authorizer)
+ mockWebhooksRepository := new(mocks.WebhooksRepository)
+
+ space := &coretypes.SpaceCore{ID: 2}
+ regInfo := ®istrytypes.RegistryRequestBaseInfo{
+ RegistryID: 1,
+ RegistryIdentifier: "reg",
+ ParentID: 2,
+ ParentRef: "root/parent",
+ RegistryType: api.RegistryTypeVIRTUAL,
+ }
+
+ permissionChecks := []coretypes.PermissionCheck{
+ {
+ Scope: coretypes.Scope{SpacePath: "root/parent"},
+ Resource: coretypes.Resource{Type: enum.ResourceTypeRegistry, Identifier: "reg"},
+ Permission: enum.PermissionRegistryEdit,
+ },
+ }
+
+ webhook := &coretypes.WebhookCore{
+ ID: 1,
+ Type: enum.WebhookTypeExternal,
+ CreatedBy: 0,
+ }
+
+ mockSpaceFinder.On("FindByRef", mock.Anything, "root/parent").
+ Return(space, nil)
+ mockRegistryMetadataHelper.On("GetRegistryRequestBaseInfo", mock.Anything, "", "reg").
+ Return(regInfo, nil)
+ mockRegistryMetadataHelper.On("GetPermissionChecks", space, "reg", enum.PermissionRegistryEdit).
+ Return(permissionChecks)
+ // Set up authorizer to expect a session with Principal ID 123 for this test case
+ mockSession := &auth.Session{Principal: coretypes.Principal{ID: 123}}
+ mockAuthorizer.On("CheckAll", mock.Anything, mockSession, permissionChecks[0]).
+ Return(true, nil)
+ mockRegistryMetadataHelper.On("MapToWebhookCore", mock.Anything,
+ mock.MatchedBy(func(req api.WebhookRequest) bool {
+ return req.Identifier == testWebhookIdentifier &&
+ req.Name == testWebhookIdentifier &&
+ req.Url == testWebhookURL &&
+ req.Enabled == true &&
+ req.Insecure == false
+ }), regInfo).
+ Return(webhook, nil)
+ mockWebhooksRepository.On("Create", mock.Anything, webhook).
+ Return(fmt.Errorf("resource is a duplicate"))
+
+ c.SpaceFinder = mockSpaceFinder
+ c.RegistryMetadataHelper = mockRegistryMetadataHelper
+ c.Authorizer = mockAuthorizer
+ c.WebhooksRepository = mockWebhooksRepository
+ },
+ request: api.CreateWebhookRequestObject{
+ RegistryRef: "reg",
+ Body: &api.CreateWebhookJSONRequestBody{
+ Name: testWebhookIdentifier,
+ Identifier: testWebhookIdentifier,
+ Url: "http://example.com",
+ Enabled: true,
+ Insecure: false,
+ },
+ },
+ expectedResp: api.CreateWebhook400JSONResponse{
+ BadRequestJSONResponse: api.BadRequestJSONResponse{
+ Code: "400",
+ Message: "failed to store webhook, Webhook with identifier test-webhook already exists",
+ },
+ },
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ // Create controller and setup mocks.
+ controller := &metadata.APIController{}
+ tt.setupMocks(controller)
+
+ // Create a context with auth session for success case
+ localCtx := context.Background()
+
+ // Add auth session for tests that need it to set CreatedBy field
+ if tt.name == "success_case" || tt.name == "duplicate_webhook_identifier" {
+ mockPrincipal := coretypes.Principal{ID: 123}
+ mockSession := &auth.Session{Principal: mockPrincipal}
+ localCtx = request.WithAuthSession(localCtx, mockSession)
+ }
+
+ // Execute.
+ resp, err := controller.CreateWebhook(localCtx, tt.request)
+
+ // Verify response matches expected type and content.
+ switch expected := tt.expectedResp.(type) {
+ case api.CreateWebhook201JSONResponse:
+ assert.NoError(t, err, "Expected no error but got one")
+ actualResp, ok := resp.(api.CreateWebhook201JSONResponse)
+ assert.True(t, ok, "Expected 201 response")
+
+ // Verify webhook data fields individually.
+ assert.Equal(t, expected.Data.Identifier, actualResp.Data.Identifier, "Webhook identifier should match")
+ assert.Equal(t, expected.Data.Name, actualResp.Data.Name, "Webhook name should match")
+ assert.Equal(t, expected.Data.Url, actualResp.Data.Url, "Webhook URL should match")
+ assert.Equal(t, expected.Data.Enabled, actualResp.Data.Enabled, "Enabled status should match")
+ assert.Equal(t, expected.Data.Insecure, actualResp.Data.Insecure, "Insecure status should match")
+ assert.NotEmpty(t, actualResp.Data.CreatedAt, "CreatedAt should not be empty")
+ assert.NotEmpty(t, actualResp.Data.ModifiedAt, "ModifiedAt should not be empty")
+ assert.Equal(t, api.StatusSUCCESS, actualResp.Status, "Status should be SUCCESS")
+
+ case api.CreateWebhook400JSONResponse:
+ // For error responses, we don't need to check the err value since responses with error codes are still valid responses
+ actualResp, ok := resp.(api.CreateWebhook400JSONResponse)
+ assert.True(t, ok, "Expected 400 response")
+ assert.Equal(t, expected.Code, actualResp.Code, "Error code should match")
+ assert.Equal(t, expected.Message, actualResp.Message, "Error message should match")
+
+ case api.CreateWebhook403JSONResponse:
+ // For error responses, we don't need to check the err value since responses with error codes are still valid responses
+ actualResp, ok := resp.(api.CreateWebhook403JSONResponse)
+ assert.True(t, ok, "Expected 403 response")
+ assert.Equal(t, expected.Code, actualResp.Code, "Error code should match")
+ assert.Equal(t, expected.Message, actualResp.Message, "Error message should match")
+
+ default:
+ t.Fatalf("Unexpected response type: %T", tt.expectedResp)
+ }
+
+ // Verify mock expectations
+ if mockSpaceFinder, ok := controller.SpaceFinder.(*mocks.SpaceFinder); ok {
+ mockSpaceFinder.AssertExpectations(t)
+ }
+ if mockMetadataHelper, ok := controller.RegistryMetadataHelper.(*mocks.RegistryMetadataHelper); ok {
+ mockMetadataHelper.AssertExpectations(t)
+ }
+ if mockWebhooksRepo, ok := controller.WebhooksRepository.(*mocks.WebhooksRepository); ok {
+ mockWebhooksRepo.AssertExpectations(t)
+ }
+ if mockAuditService, ok := controller.AuditService.(*mocks.AuditService); ok {
+ mockAuditService.AssertExpectations(t)
+ }
+ })
+ }
+}
diff --git a/registry/app/api/controller/metadata/delete_artifact.go b/registry/app/api/controller/metadata/delete_artifact.go
index 99627f6d5..b6b3a94ad 100644
--- a/registry/app/api/controller/metadata/delete_artifact.go
+++ b/registry/app/api/controller/metadata/delete_artifact.go
@@ -24,6 +24,7 @@ import (
"github.com/harness/gitness/audit"
"github.com/harness/gitness/registry/app/api/openapi/contracts/artifact"
"github.com/harness/gitness/registry/app/api/utils"
+ registryTypes "github.com/harness/gitness/registry/types"
"github.com/harness/gitness/types/enum"
"github.com/rs/zerolog/log"
@@ -64,7 +65,7 @@ func (c *APIController) DeleteArtifact(ctx context.Context, r artifact.DeleteArt
}, err
}
- repoEntity, err := c.RegistryRepository.GetByParentIDAndName(ctx, regInfo.parentID, regInfo.RegistryIdentifier)
+ repoEntity, err := c.RegistryRepository.GetByParentIDAndName(ctx, regInfo.ParentID, regInfo.RegistryIdentifier)
if err != nil {
//nolint:nilerr
return artifact.DeleteArtifact404JSONResponse{
@@ -130,7 +131,7 @@ func (c *APIController) DeleteArtifact(ctx context.Context, r artifact.DeleteArt
func (c *APIController) deleteOCIImage(
ctx context.Context,
- regInfo *RegistryRequestBaseInfo,
+ regInfo *registryTypes.RegistryRequestBaseInfo,
artifactName string,
) error {
err := c.tx.WithTx(
@@ -156,7 +157,7 @@ func (c *APIController) deleteOCIImage(
func (c *APIController) deleteGenericImage(
ctx context.Context,
- regInfo *RegistryRequestBaseInfo,
+ regInfo *registryTypes.RegistryRequestBaseInfo,
artifactName string,
) error {
err := c.tx.WithTx(
diff --git a/registry/app/api/controller/metadata/delete_artifact_test.go b/registry/app/api/controller/metadata/delete_artifact_test.go
new file mode 100644
index 000000000..f07fc7dfb
--- /dev/null
+++ b/registry/app/api/controller/metadata/delete_artifact_test.go
@@ -0,0 +1,458 @@
+// Copyright 2023 Harness, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package metadata
+
+import (
+ "context"
+ "fmt"
+ "testing"
+
+ "github.com/harness/gitness/app/api/request"
+ "github.com/harness/gitness/app/auth"
+ "github.com/harness/gitness/audit"
+ "github.com/harness/gitness/registry/app/api/controller/mocks"
+ api "github.com/harness/gitness/registry/app/api/openapi/contracts/artifact"
+ "github.com/harness/gitness/registry/types"
+ coretypes "github.com/harness/gitness/types"
+ "github.com/harness/gitness/types/enum"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/mock"
+)
+
+func TestDeleteArtifact(t *testing.T) {
+ // Create a mock session for testing
+ principal := coretypes.Principal{
+ ID: 1,
+ Type: enum.PrincipalTypeUser,
+ Email: "test@example.com",
+ }
+ mockSession := &auth.Session{
+ Principal: principal,
+ }
+
+ // Create a context with the mock session
+ testCtx := request.WithAuthSession(context.Background(), mockSession)
+
+ tests := []struct {
+ name string
+ setupMocks func(*APIController)
+ request api.DeleteArtifactRequestObject
+ expectedResp api.DeleteArtifactResponseObject
+ expectedError error
+ }{
+ {
+ name: "success_case",
+ setupMocks: func(c *APIController) {
+ mockSpaceFinder := new(mocks.SpaceFinder)
+ mockRegistryRepository := new(mocks.RegistryRepository)
+ mockAuthorizer := new(mocks.Authorizer)
+ mockRegistryMetadataHelper := new(mocks.RegistryMetadataHelper)
+ mockImageStore := new(mocks.ImageRepository)
+ mockTx := new(mocks.Transaction)
+ mockAuditService := new(mocks.AuditService)
+
+ space := &coretypes.SpaceCore{ID: 2}
+ regInfo := &types.RegistryRequestBaseInfo{
+ RegistryID: 1,
+ RegistryIdentifier: "reg",
+ ParentID: 2,
+ ParentRef: "root/parent",
+ PackageType: api.PackageTypePYTHON,
+ }
+
+ registry := &types.Registry{
+ ID: 1,
+ Name: "reg",
+ ParentID: 2,
+ Type: "native",
+ PackageType: "pypi",
+ }
+
+ artifact := &types.Image{
+ ID: 1,
+ Name: "test-artifact",
+ Enabled: true,
+ RegistryID: regInfo.RegistryID,
+ }
+
+ mockSpaceFinder.On("FindByRef", mock.Anything, "root/parent").Return(space, nil)
+ mockRegistryMetadataHelper.On("GetRegistryRequestBaseInfo",
+ mock.Anything, "", "reg").Return(regInfo, nil)
+ mockAuthorizer.On(
+ "Check",
+ mock.Anything,
+ mock.AnythingOfType("*auth.Session"),
+ mock.AnythingOfType("*types.Scope"),
+ mock.AnythingOfType("*types.Resource"),
+ enum.PermissionArtifactsDelete,
+ ).Return(true, nil)
+ mockRegistryRepository.On(
+ "GetByParentIDAndName",
+ mock.Anything,
+ int64(2),
+ "reg",
+ ).Return(registry, nil)
+ mockImageStore.On(
+ "GetByName",
+ mock.Anything,
+ int64(1),
+ "test-artifact",
+ ).Return(artifact, nil)
+ mockTx.On("WithTx", mock.Anything, mock.AnythingOfType("func(context.Context) error")).Return(nil)
+ mockAuditService.On(
+ "Log",
+ mock.Anything,
+ mock.AnythingOfType("types.Principal"),
+ mock.AnythingOfType("audit.Resource"),
+ audit.ActionDeleted,
+ "root/parent",
+ mock.Anything,
+ mock.Anything,
+ ).Return(nil)
+
+ c.SpaceFinder = mockSpaceFinder
+ c.RegistryRepository = mockRegistryRepository
+ c.Authorizer = mockAuthorizer
+ c.RegistryMetadataHelper = mockRegistryMetadataHelper
+ c.ImageStore = mockImageStore
+ c.tx = mockTx
+ c.AuditService = mockAuditService
+ },
+ request: api.DeleteArtifactRequestObject{
+ RegistryRef: "reg",
+ Artifact: "test-artifact",
+ },
+ expectedResp: api.DeleteArtifact200JSONResponse{
+ SuccessJSONResponse: api.SuccessJSONResponse{
+ Status: api.StatusSUCCESS,
+ },
+ },
+ },
+ {
+ name: "invalid_registry_reference",
+ setupMocks: func(c *APIController) {
+ mockRegistryMetadataHelper := new(mocks.RegistryMetadataHelper)
+ mockRegistryMetadataHelper.On("GetRegistryRequestBaseInfo",
+ mock.Anything, "", "invalid-reg").Return(nil, fmt.Errorf("invalid registry reference"))
+ c.RegistryMetadataHelper = mockRegistryMetadataHelper
+ },
+ request: api.DeleteArtifactRequestObject{
+ RegistryRef: "invalid-reg",
+ Artifact: "test-artifact",
+ },
+ expectedResp: api.DeleteArtifact400JSONResponse{
+ BadRequestJSONResponse: api.BadRequestJSONResponse{
+ Code: "400",
+ Message: "invalid registry reference",
+ },
+ },
+ expectedError: fmt.Errorf("invalid registry reference"),
+ },
+ {
+ name: "permission_check_fails",
+ setupMocks: func(c *APIController) {
+ mockSpaceFinder := new(mocks.SpaceFinder)
+ mockRegistryMetadataHelper := new(mocks.RegistryMetadataHelper)
+ mockAuthorizer := new(mocks.Authorizer)
+
+ space := &coretypes.SpaceCore{ID: 2}
+ regInfo := &types.RegistryRequestBaseInfo{
+ RegistryID: 1,
+ RegistryIdentifier: "reg",
+ ParentID: 2,
+ ParentRef: "root/parent",
+ PackageType: api.PackageTypePYTHON,
+ }
+
+ mockSpaceFinder.On("FindByRef", mock.Anything, "root/parent").Return(space, nil)
+ mockRegistryMetadataHelper.On("GetRegistryRequestBaseInfo",
+ mock.Anything, "", "reg").Return(regInfo, nil)
+ mockAuthorizer.On("Check", mock.Anything, mock.AnythingOfType("*auth.Session"),
+ mock.AnythingOfType("*types.Scope"),
+ mock.AnythingOfType("*types.Resource"),
+ enum.PermissionArtifactsDelete).Return(false, fmt.Errorf("not authorized"))
+
+ c.SpaceFinder = mockSpaceFinder
+ c.RegistryMetadataHelper = mockRegistryMetadataHelper
+ c.Authorizer = mockAuthorizer
+ },
+ request: api.DeleteArtifactRequestObject{
+ RegistryRef: "reg",
+ Artifact: "test-artifact",
+ },
+ expectedResp: api.DeleteArtifact403JSONResponse{
+ UnauthorizedJSONResponse: api.UnauthorizedJSONResponse{
+ Code: "403",
+ Message: "not authorized",
+ },
+ },
+ expectedError: fmt.Errorf("not authorized"),
+ },
+ {
+ name: "registry_not_found",
+ setupMocks: func(c *APIController) {
+ mockSpaceFinder := new(mocks.SpaceFinder)
+ mockRegistryRepository := new(mocks.RegistryRepository)
+ mockAuthorizer := new(mocks.Authorizer)
+ mockRegistryMetadataHelper := new(mocks.RegistryMetadataHelper)
+
+ space := &coretypes.SpaceCore{ID: 2}
+ regInfo := &types.RegistryRequestBaseInfo{
+ RegistryID: 1,
+ RegistryIdentifier: "reg",
+ ParentID: 2,
+ ParentRef: "root/parent",
+ PackageType: api.PackageTypePYTHON,
+ }
+
+ mockSpaceFinder.On("FindByRef", mock.Anything, "root/parent").Return(space, nil)
+ mockRegistryMetadataHelper.On("GetRegistryRequestBaseInfo",
+ mock.Anything, "", "reg").Return(regInfo, nil)
+ mockAuthorizer.On(
+ "Check",
+ mock.Anything,
+ mock.AnythingOfType("*auth.Session"),
+ mock.AnythingOfType("*types.Scope"),
+ mock.AnythingOfType("*types.Resource"),
+ enum.PermissionArtifactsDelete,
+ ).Return(true, nil)
+ mockRegistryRepository.On(
+ "GetByParentIDAndName",
+ mock.Anything,
+ int64(2),
+ "reg",
+ ).Return(nil, fmt.Errorf("registry doesn't exist with this key"))
+
+ c.SpaceFinder = mockSpaceFinder
+ c.RegistryRepository = mockRegistryRepository
+ c.Authorizer = mockAuthorizer
+ c.RegistryMetadataHelper = mockRegistryMetadataHelper
+ },
+ request: api.DeleteArtifactRequestObject{
+ RegistryRef: "reg",
+ Artifact: "test-artifact",
+ },
+ expectedResp: api.DeleteArtifact404JSONResponse{
+ NotFoundJSONResponse: api.NotFoundJSONResponse{
+ Code: "404",
+ Message: "registry doesn't exist with this key",
+ },
+ },
+ },
+ {
+ name: "artifact_not_found",
+ setupMocks: func(c *APIController) {
+ mockSpaceFinder := new(mocks.SpaceFinder)
+ mockRegistryRepository := new(mocks.RegistryRepository)
+ mockAuthorizer := new(mocks.Authorizer)
+ mockRegistryMetadataHelper := new(mocks.RegistryMetadataHelper)
+ mockImageStore := new(mocks.ImageRepository)
+ mockAuditService := new(mocks.AuditService)
+
+ space := &coretypes.SpaceCore{ID: 2}
+ regInfo := &types.RegistryRequestBaseInfo{
+ RegistryID: 1,
+ RegistryIdentifier: "reg",
+ ParentID: 2,
+ ParentRef: "root/parent",
+ PackageType: api.PackageTypePYTHON,
+ }
+
+ registry := &types.Registry{
+ ID: 1,
+ Name: "reg",
+ ParentID: 2,
+ Type: "native",
+ PackageType: "pypi",
+ }
+
+ mockSpaceFinder.On("FindByRef", mock.Anything, "root/parent").Return(space, nil)
+ mockRegistryMetadataHelper.On("GetRegistryRequestBaseInfo",
+ mock.Anything, "", "reg").Return(regInfo, nil)
+ mockAuthorizer.On(
+ "Check",
+ mock.Anything,
+ mock.AnythingOfType("*auth.Session"),
+ mock.AnythingOfType("*types.Scope"),
+ mock.AnythingOfType("*types.Resource"),
+ enum.PermissionArtifactsDelete,
+ ).Return(true, nil)
+ mockRegistryRepository.On(
+ "GetByParentIDAndName",
+ mock.Anything,
+ int64(2),
+ "reg",
+ ).Return(registry, nil)
+ mockImageStore.On(
+ "GetByName",
+ mock.Anything,
+ int64(1),
+ "non-existent-artifact",
+ ).Return(nil, fmt.Errorf("artifact doesn't exist with this key"))
+
+ c.SpaceFinder = mockSpaceFinder
+ c.RegistryRepository = mockRegistryRepository
+ c.Authorizer = mockAuthorizer
+ c.RegistryMetadataHelper = mockRegistryMetadataHelper
+ c.ImageStore = mockImageStore
+ c.AuditService = mockAuditService
+ },
+ request: api.DeleteArtifactRequestObject{
+ RegistryRef: "reg",
+ Artifact: "non-existent-artifact",
+ },
+ expectedResp: api.DeleteArtifact404JSONResponse{
+ NotFoundJSONResponse: api.NotFoundJSONResponse{
+ Code: "404",
+ Message: "artifact doesn't exist with this key",
+ },
+ },
+ },
+ {
+ name: "artifact_already_deleted",
+ setupMocks: func(c *APIController) {
+ mockSpaceFinder := new(mocks.SpaceFinder)
+ mockRegistryRepository := new(mocks.RegistryRepository)
+ mockAuthorizer := new(mocks.Authorizer)
+ mockRegistryMetadataHelper := new(mocks.RegistryMetadataHelper)
+ mockImageStore := new(mocks.ImageRepository)
+ mockAuditService := new(mocks.AuditService)
+
+ space := &coretypes.SpaceCore{ID: 2}
+ regInfo := &types.RegistryRequestBaseInfo{
+ RegistryID: 1,
+ RegistryIdentifier: "reg",
+ ParentID: 2,
+ ParentRef: "root/parent",
+ PackageType: api.PackageTypePYTHON,
+ }
+
+ registry := &types.Registry{
+ ID: 1,
+ Name: "reg",
+ ParentID: 2,
+ Type: "native",
+ PackageType: "pypi",
+ }
+
+ mockSpaceFinder.On("FindByRef", mock.Anything, "root/parent").Return(space, nil)
+ mockRegistryMetadataHelper.On("GetRegistryRequestBaseInfo",
+ mock.Anything, "", "reg").Return(regInfo, nil)
+ mockAuthorizer.On(
+ "Check",
+ mock.Anything,
+ mock.AnythingOfType("*auth.Session"),
+ mock.AnythingOfType("*types.Scope"),
+ mock.AnythingOfType("*types.Resource"),
+ enum.PermissionArtifactsDelete,
+ ).Return(true, nil)
+ mockRegistryRepository.On(
+ "GetByParentIDAndName",
+ mock.Anything,
+ int64(2),
+ "reg",
+ ).Return(registry, nil)
+ mockImageStore.On(
+ "GetByName",
+ mock.Anything,
+ int64(1),
+ "deleted-artifact",
+ ).Return(nil, fmt.Errorf("artifact is already deleted"))
+
+ c.SpaceFinder = mockSpaceFinder
+ c.RegistryRepository = mockRegistryRepository
+ c.Authorizer = mockAuthorizer
+ c.RegistryMetadataHelper = mockRegistryMetadataHelper
+ c.ImageStore = mockImageStore
+ c.AuditService = mockAuditService
+ },
+ request: api.DeleteArtifactRequestObject{
+ RegistryRef: "reg",
+ Artifact: "deleted-artifact",
+ },
+ expectedResp: api.DeleteArtifact404JSONResponse{
+ NotFoundJSONResponse: api.NotFoundJSONResponse{
+ Code: "404",
+ Message: "artifact doesn't exist with this key",
+ },
+ },
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ c := &APIController{}
+ tt.setupMocks(c)
+
+ // Use the test context with the mock session
+ resp, err := c.DeleteArtifact(testCtx, tt.request)
+
+ if tt.expectedError != nil {
+ assert.Error(t, err, "Expected an error")
+ assert.Equal(t, tt.expectedError.Error(), err.Error(), "Error message should match")
+ } else {
+ assert.NoError(t, err, "Expected no error")
+ }
+
+ // Check response type
+ switch expected := tt.expectedResp.(type) {
+ case api.DeleteArtifact200JSONResponse:
+ actual, ok := resp.(api.DeleteArtifact200JSONResponse)
+ assert.True(t, ok, "Expected 200 success response")
+ assert.Equal(t, expected.Status, actual.Status, "Response status should match")
+ case api.DeleteArtifact400JSONResponse:
+ actual, ok := resp.(api.DeleteArtifact400JSONResponse)
+ assert.True(t, ok, "Expected 400 bad request response")
+ assert.Equal(t, expected.Message, actual.Message, "Error message should match")
+ case api.DeleteArtifact403JSONResponse:
+ actual, ok := resp.(api.DeleteArtifact403JSONResponse)
+ assert.True(t, ok, "Expected 403 forbidden response")
+ assert.Equal(t, expected.Message, actual.Message, "Error message should match")
+ case api.DeleteArtifact404JSONResponse:
+ actual, ok := resp.(api.DeleteArtifact404JSONResponse)
+ assert.True(t, ok, "Expected 404 not found response")
+ assert.Equal(t, expected.Message, actual.Message, "Error message should match")
+ }
+
+ // Full response should match expected value
+ assert.Equal(t, tt.expectedResp, resp, "Full response should match expected value")
+
+ // Verify all expectations were met
+ // Only verify mocks that were actually set up in this test case
+ if c.SpaceFinder != nil {
+ mock.AssertExpectationsForObjects(t, c.SpaceFinder)
+ }
+ if c.RegistryRepository != nil {
+ mock.AssertExpectationsForObjects(t, c.RegistryRepository)
+ }
+ if c.Authorizer != nil {
+ mock.AssertExpectationsForObjects(t, c.Authorizer)
+ }
+ if c.RegistryMetadataHelper != nil {
+ mock.AssertExpectationsForObjects(t, c.RegistryMetadataHelper)
+ }
+ if c.ImageStore != nil {
+ mock.AssertExpectationsForObjects(t, c.ImageStore)
+ }
+ if c.tx != nil {
+ mock.AssertExpectationsForObjects(t, c.tx)
+ }
+ if c.AuditService != nil {
+ mock.AssertExpectationsForObjects(t, c.AuditService)
+ }
+ })
+ }
+}
diff --git a/registry/app/api/controller/metadata/delete_artifacts_version.go b/registry/app/api/controller/metadata/delete_artifacts_version.go
index 5421ec792..93dfc75f2 100644
--- a/registry/app/api/controller/metadata/delete_artifacts_version.go
+++ b/registry/app/api/controller/metadata/delete_artifacts_version.go
@@ -25,6 +25,7 @@ import (
"github.com/harness/gitness/registry/app/api/openapi/contracts/artifact"
"github.com/harness/gitness/registry/app/api/utils"
"github.com/harness/gitness/registry/services/webhook"
+ registryTypes "github.com/harness/gitness/registry/types"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
@@ -67,7 +68,7 @@ func (c *APIController) DeleteArtifactVersion(ctx context.Context, r artifact.De
}, err
}
- repoEntity, err := c.RegistryRepository.GetByParentIDAndName(ctx, regInfo.parentID, regInfo.RegistryIdentifier)
+ repoEntity, err := c.RegistryRepository.GetByParentIDAndName(ctx, regInfo.ParentID, regInfo.RegistryIdentifier)
if err != nil {
//nolint:nilerr
return artifact.DeleteArtifactVersion404JSONResponse{
@@ -81,7 +82,7 @@ func (c *APIController) DeleteArtifactVersion(ctx context.Context, r artifact.De
versionName := string(r.Version)
registryName := repoEntity.Name
- image, err := c.ImageStore.GetByRepoAndName(ctx, regInfo.parentID, regInfo.RegistryIdentifier, artifactName)
+ image, err := c.ImageStore.GetByRepoAndName(ctx, regInfo.ParentID, regInfo.RegistryIdentifier, artifactName)
if err != nil {
//nolint:nilerr
return artifact.DeleteArtifactVersion404JSONResponse{
@@ -103,10 +104,10 @@ func (c *APIController) DeleteArtifactVersion(ctx context.Context, r artifact.De
switch regInfo.PackageType {
case artifact.PackageTypeDOCKER:
- err = c.deleteTag(ctx, regInfo, registryName, session.Principal, artifactName,
+ err = c.deleteTagWithAudit(ctx, regInfo, registryName, session.Principal, artifactName,
versionName)
case artifact.PackageTypeHELM:
- err = c.deleteTag(ctx, regInfo, registryName, session.Principal, artifactName,
+ err = c.deleteTagWithAudit(ctx, regInfo, registryName, session.Principal, artifactName,
versionName)
case artifact.PackageTypeNPM:
err = c.deleteVersion(ctx, regInfo, artifactName, versionName)
@@ -147,8 +148,8 @@ func (c *APIController) DeleteArtifactVersion(ctx context.Context, r artifact.De
}, nil
}
-func (c *APIController) deleteTag(
- ctx context.Context, regInfo *RegistryRequestBaseInfo,
+func (c *APIController) deleteTagWithAudit(
+ ctx context.Context, regInfo *registryTypes.RegistryRequestBaseInfo,
registryName string, principal types.Principal, artifactName string, versionName string,
) error {
existingDigest := c.getTagDigest(ctx, regInfo.RegistryID, artifactName, versionName)
@@ -170,7 +171,7 @@ func (c *APIController) deleteTag(
func (c *APIController) deleteVersion(
ctx context.Context,
- regInfo *RegistryRequestBaseInfo,
+ regInfo *registryTypes.RegistryRequestBaseInfo,
artifactName string,
versionName string,
) error {
diff --git a/registry/app/api/controller/metadata/delete_registry.go b/registry/app/api/controller/metadata/delete_registry.go
index c6cc28b35..ef7aefbb1 100644
--- a/registry/app/api/controller/metadata/delete_registry.go
+++ b/registry/app/api/controller/metadata/delete_registry.go
@@ -69,7 +69,7 @@ func (c *APIController) DeleteRegistry(
}, err
}
- repoEntity, err := c.RegistryRepository.GetByParentIDAndName(ctx, regInfo.parentID, regInfo.RegistryIdentifier)
+ repoEntity, err := c.RegistryRepository.GetByParentIDAndName(ctx, regInfo.ParentID, regInfo.RegistryIdentifier)
if err != nil {
//nolint:nilerr
return artifact.DeleteRegistry404JSONResponse{
@@ -132,10 +132,10 @@ func (c *APIController) DeleteRegistry(
func (c *APIController) deleteUpstreamProxyWithAudit(
ctx context.Context,
- regInfo *RegistryRequestBaseInfo, principal types.Principal, parentRef string, registryName string,
+ regInfo *registrytypes.RegistryRequestBaseInfo, principal types.Principal, parentRef string, registryName string,
) error {
upstreamProxies, err := c.RegistryRepository.FetchUpstreamProxyIDs(ctx,
- []string{regInfo.RegistryIdentifier}, regInfo.parentID)
+ []string{regInfo.RegistryIdentifier}, regInfo.ParentID)
if err != nil {
log.Ctx(ctx).Error().Msgf("failed to fetch upstream proxy IDs: %s", err)
return fmt.Errorf("failed to fectch upstream proxy IDs :%w", err)
@@ -143,7 +143,7 @@ func (c *APIController) deleteUpstreamProxyWithAudit(
//nolint:nestif
if len(upstreamProxies) > 0 {
registryIDs, err := c.RegistryRepository.FetchRegistriesIDByUpstreamProxyID(
- ctx, strconv.FormatInt(upstreamProxies[0], 10), regInfo.rootIdentifierID)
+ ctx, strconv.FormatInt(upstreamProxies[0], 10), regInfo.RootIdentifierID)
if err != nil {
log.Ctx(ctx).Error().Msgf("failed to fetch registryIDs: %s", err)
return fmt.Errorf("failed to fetch registryIDs IDs :%w", err)
@@ -168,7 +168,7 @@ func (c *APIController) deleteUpstreamProxyWithAudit(
}
}
- err = c.UpstreamProxyStore.Delete(ctx, regInfo.parentID, regInfo.RegistryIdentifier)
+ err = c.UpstreamProxyStore.Delete(ctx, regInfo.ParentID, regInfo.RegistryIdentifier)
if err != nil {
return err
}
@@ -191,7 +191,7 @@ func (c *APIController) deleteUpstreamProxyWithAudit(
}
func (c *APIController) deleteRegistryWithAudit(
- ctx context.Context, regInfo *RegistryRequestBaseInfo,
+ ctx context.Context, regInfo *registrytypes.RegistryRequestBaseInfo,
registry *registrytypes.Registry, principal types.Principal, parentRef string,
) error {
err := c.ImageStore.DeleteByRegistryID(ctx, regInfo.RegistryID)
@@ -204,7 +204,7 @@ func (c *APIController) deleteRegistryWithAudit(
return err
}
- err = c.RegistryRepository.Delete(ctx, regInfo.parentID, regInfo.RegistryIdentifier)
+ err = c.RegistryRepository.Delete(ctx, regInfo.ParentID, regInfo.RegistryIdentifier)
if err != nil {
return err
}
diff --git a/registry/app/api/controller/metadata/delete_registry_test.go b/registry/app/api/controller/metadata/delete_registry_test.go
new file mode 100644
index 000000000..6921c15ca
--- /dev/null
+++ b/registry/app/api/controller/metadata/delete_registry_test.go
@@ -0,0 +1,475 @@
+// Copyright 2023 Harness, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package metadata
+
+import (
+ "context"
+ "fmt"
+ "testing"
+
+ "github.com/harness/gitness/app/api/request"
+ "github.com/harness/gitness/app/auth"
+ "github.com/harness/gitness/registry/app/api/controller/mocks"
+ api "github.com/harness/gitness/registry/app/api/openapi/contracts/artifact"
+ "github.com/harness/gitness/registry/types"
+ coretypes "github.com/harness/gitness/types"
+ "github.com/harness/gitness/types/enum"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/mock"
+)
+
+func TestDeleteRegistry(t *testing.T) {
+ // Create a mock session for testing
+ principal := coretypes.Principal{
+ ID: 1,
+ Type: enum.PrincipalTypeUser,
+ Email: "test@example.com",
+ }
+ mockSession := &auth.Session{
+ Principal: principal,
+ }
+
+ // Create a context with the mock session
+ testCtx := request.WithAuthSession(context.Background(), mockSession)
+
+ tests := []struct {
+ name string
+ setupMocks func(*APIController)
+ request api.DeleteRegistryRequestObject
+ expectedResp api.DeleteRegistryResponseObject
+ expectedError error
+ }{
+ {
+ name: "success_case_virtual_registry",
+ setupMocks: func(c *APIController) {
+ mockSpaceFinder := new(mocks.SpaceFinder)
+ mockRegistryRepository := new(mocks.RegistryRepository)
+ mockAuthorizer := new(mocks.Authorizer)
+ mockRegistryMetadataHelper := new(mocks.RegistryMetadataHelper)
+ mockImageStore := new(mocks.ImageRepository)
+ mockTx := new(mocks.Transaction)
+ mockAuditService := new(mocks.AuditService)
+
+ space := &coretypes.SpaceCore{ID: 2}
+ regInfo := &types.RegistryRequestBaseInfo{
+ RegistryID: 1,
+ RegistryIdentifier: "reg",
+ ParentID: 2,
+ ParentRef: "root/parent",
+ }
+
+ registry := &types.Registry{
+ ID: 1,
+ Name: "reg",
+ ParentID: 2,
+ Type: "virtual",
+ PackageType: "pypi",
+ }
+
+ permissionChecks := []coretypes.PermissionCheck{
+ {
+ Scope: coretypes.Scope{SpacePath: "root/parent"},
+ Resource: coretypes.Resource{Type: enum.ResourceTypeRegistry, Identifier: "reg"},
+ Permission: enum.PermissionRegistryDelete,
+ },
+ }
+
+ mockSpaceFinder.On("FindByRef", mock.Anything, "root/parent").Return(space, nil)
+ mockRegistryMetadataHelper.On("GetRegistryRequestBaseInfo", mock.Anything, "", "reg").Return(regInfo, nil)
+ mockRegistryMetadataHelper.On(
+ "GetPermissionChecks",
+ space,
+ "reg",
+ enum.PermissionRegistryDelete,
+ ).Return(permissionChecks)
+ mockAuthorizer.On(
+ "CheckAll",
+ mock.Anything,
+ mock.AnythingOfType("*auth.Session"),
+ permissionChecks[0],
+ ).Return(true, nil)
+ mockRegistryRepository.On(
+ "GetByParentIDAndName",
+ mock.Anything,
+ regInfo.ParentID,
+ regInfo.RegistryIdentifier,
+ ).Return(registry, nil)
+ mockImageStore.On("DeleteDownloadStatByRegistryID", mock.Anything, regInfo.RegistryID).Return(nil)
+ mockImageStore.On("DeleteBandwidthStatByRegistryID", mock.Anything, regInfo.RegistryID).Return(nil)
+ mockImageStore.On("DeleteByRegistryID", mock.Anything, regInfo.RegistryID).Return(nil)
+ mockRegistryRepository.On("Delete", mock.Anything, regInfo.ParentID, regInfo.RegistryIdentifier).Return(nil)
+ mockAuditService.On(
+ "Log",
+ mock.Anything,
+ mock.AnythingOfType("*types.PrincipalInfo"),
+ mock.AnythingOfType("*audit.Resource"),
+ mock.AnythingOfType("string"),
+ mock.AnythingOfType("string"),
+ mock.AnythingOfType("audit.Option"),
+ ).Return(nil)
+ // Simply return nil for the transaction - we're testing the controller logic, not transaction details
+ mockTx.On("WithTx", mock.Anything, mock.AnythingOfType("func(context.Context) error")).Return(nil)
+
+ c.SpaceFinder = mockSpaceFinder
+ c.RegistryRepository = mockRegistryRepository
+ c.Authorizer = mockAuthorizer
+ c.RegistryMetadataHelper = mockRegistryMetadataHelper
+ c.ImageStore = mockImageStore
+ c.tx = mockTx
+ c.AuditService = mockAuditService
+ },
+ request: api.DeleteRegistryRequestObject{
+ RegistryRef: "reg",
+ },
+ expectedResp: api.DeleteRegistry200JSONResponse{
+ SuccessJSONResponse: api.SuccessJSONResponse{
+ Status: api.StatusSUCCESS,
+ },
+ },
+ },
+ {
+ name: "invalid_registry_reference",
+ setupMocks: func(c *APIController) {
+ mockRegistryMetadataHelper := new(mocks.RegistryMetadataHelper)
+ mockRegistryMetadataHelper.On(
+ "GetRegistryRequestBaseInfo",
+ mock.Anything,
+ "",
+ "invalid-reg",
+ ).Return(nil, fmt.Errorf("invalid registry reference"))
+ c.RegistryMetadataHelper = mockRegistryMetadataHelper
+ },
+ request: api.DeleteRegistryRequestObject{
+ RegistryRef: "invalid-reg",
+ },
+ expectedResp: api.DeleteRegistry400JSONResponse{
+ BadRequestJSONResponse: api.BadRequestJSONResponse{
+ Code: "400",
+ Message: "invalid registry reference",
+ },
+ },
+ expectedError: fmt.Errorf("invalid registry reference"),
+ },
+ {
+ name: "permission_check_fails",
+ setupMocks: func(c *APIController) {
+ mockSpaceFinder := new(mocks.SpaceFinder)
+ mockRegistryMetadataHelper := new(mocks.RegistryMetadataHelper)
+ mockAuthorizer := new(mocks.Authorizer)
+
+ space := &coretypes.SpaceCore{ID: 2}
+ regInfo := &types.RegistryRequestBaseInfo{
+ RegistryID: 1,
+ RegistryIdentifier: "reg",
+ ParentID: 2,
+ ParentRef: "root/parent",
+ }
+
+ permissionChecks := []coretypes.PermissionCheck{
+ {
+ Scope: coretypes.Scope{SpacePath: "root/parent"},
+ Resource: coretypes.Resource{Type: enum.ResourceTypeRegistry, Identifier: "reg"},
+ Permission: enum.PermissionRegistryDelete,
+ },
+ }
+
+ mockSpaceFinder.On("FindByRef", mock.Anything, "root/parent").Return(space, nil)
+ mockRegistryMetadataHelper.On("GetRegistryRequestBaseInfo", mock.Anything, "", "reg").Return(regInfo, nil)
+ mockRegistryMetadataHelper.On(
+ "GetPermissionChecks",
+ space,
+ "reg",
+ enum.PermissionRegistryDelete,
+ ).Return(permissionChecks)
+ mockAuthorizer.On(
+ "CheckAll",
+ mock.Anything,
+ mock.AnythingOfType("*auth.Session"),
+ permissionChecks[0],
+ ).Return(false, fmt.Errorf("not authorized"))
+
+ c.SpaceFinder = mockSpaceFinder
+ c.RegistryMetadataHelper = mockRegistryMetadataHelper
+ c.Authorizer = mockAuthorizer
+ },
+ request: api.DeleteRegistryRequestObject{
+ RegistryRef: "reg",
+ },
+ expectedResp: api.DeleteRegistry403JSONResponse{
+ UnauthorizedJSONResponse: api.UnauthorizedJSONResponse{
+ Code: "403",
+ Message: "not authorized",
+ },
+ },
+ expectedError: fmt.Errorf("not authorized"),
+ },
+ {
+ name: "registry_not_found",
+ setupMocks: func(c *APIController) {
+ mockSpaceFinder := new(mocks.SpaceFinder)
+ mockRegistryRepository := new(mocks.RegistryRepository)
+ mockAuthorizer := new(mocks.Authorizer)
+ mockRegistryMetadataHelper := new(mocks.RegistryMetadataHelper)
+
+ space := &coretypes.SpaceCore{ID: 2}
+ regInfo := &types.RegistryRequestBaseInfo{
+ RegistryID: 1,
+ RegistryIdentifier: "reg",
+ ParentID: 2,
+ ParentRef: "root/parent",
+ }
+
+ permissionChecks := []coretypes.PermissionCheck{
+ {
+ Scope: coretypes.Scope{SpacePath: "root/parent"},
+ Resource: coretypes.Resource{Type: enum.ResourceTypeRegistry, Identifier: "reg"},
+ Permission: enum.PermissionRegistryDelete,
+ },
+ }
+
+ mockSpaceFinder.On("FindByRef", mock.Anything, "root/parent").Return(space, nil)
+ mockRegistryMetadataHelper.On("GetRegistryRequestBaseInfo", mock.Anything, "", "reg").Return(regInfo, nil)
+ mockRegistryMetadataHelper.On(
+ "GetPermissionChecks",
+ space,
+ "reg",
+ enum.PermissionRegistryDelete,
+ ).Return(permissionChecks)
+ mockAuthorizer.On(
+ "CheckAll",
+ mock.Anything,
+ mock.AnythingOfType("*auth.Session"),
+ permissionChecks[0],
+ ).Return(true, nil)
+ mockRegistryRepository.On(
+ "GetByParentIDAndName",
+ mock.Anything,
+ regInfo.ParentID,
+ regInfo.RegistryIdentifier,
+ ).Return(nil, fmt.Errorf("registry doesn't exist with this key"))
+
+ c.SpaceFinder = mockSpaceFinder
+ c.RegistryRepository = mockRegistryRepository
+ c.Authorizer = mockAuthorizer
+ c.RegistryMetadataHelper = mockRegistryMetadataHelper
+ },
+ request: api.DeleteRegistryRequestObject{
+ RegistryRef: "reg",
+ },
+ expectedResp: api.DeleteRegistry404JSONResponse{
+ NotFoundJSONResponse: api.NotFoundJSONResponse{
+ Code: "404",
+ Message: "registry doesn't exist with this key",
+ },
+ },
+ },
+ {
+ name: "success_case_native_registry",
+ setupMocks: func(c *APIController) {
+ mockSpaceFinder := new(mocks.SpaceFinder)
+ mockRegistryRepository := new(mocks.RegistryRepository)
+ mockAuthorizer := new(mocks.Authorizer)
+ mockRegistryMetadataHelper := new(mocks.RegistryMetadataHelper)
+ mockImageStore := new(mocks.ImageRepository)
+ mockTx := new(mocks.Transaction)
+ mockAuditService := new(mocks.AuditService)
+ mockUpstreamProxyStore := new(mocks.UpstreamProxyStore)
+
+ space := &coretypes.SpaceCore{ID: 2}
+ regInfo := &types.RegistryRequestBaseInfo{
+ RegistryID: 1,
+ RegistryIdentifier: "reg",
+ ParentID: 2,
+ ParentRef: "root/parent",
+ }
+
+ registry := &types.Registry{
+ ID: 1,
+ Name: "reg",
+ ParentID: 2,
+ Type: "native",
+ PackageType: "pypi",
+ }
+
+ permissionChecks := []coretypes.PermissionCheck{
+ {
+ Scope: coretypes.Scope{SpacePath: "root/parent"},
+ Resource: coretypes.Resource{Type: enum.ResourceTypeRegistry, Identifier: "reg"},
+ Permission: enum.PermissionRegistryDelete,
+ },
+ }
+
+ mockSpaceFinder.On("FindByRef", mock.Anything, "root/parent").Return(space, nil)
+ mockRegistryMetadataHelper.On("GetRegistryRequestBaseInfo", mock.Anything, "", "reg").Return(regInfo, nil)
+ mockRegistryMetadataHelper.On(
+ "GetPermissionChecks",
+ space,
+ "reg",
+ enum.PermissionRegistryDelete,
+ ).Return(permissionChecks)
+ mockAuthorizer.On(
+ "CheckAll",
+ mock.Anything,
+ mock.AnythingOfType("*auth.Session"),
+ permissionChecks[0],
+ ).Return(true, nil)
+ mockRegistryRepository.On(
+ "GetByParentIDAndName",
+ mock.Anything,
+ regInfo.ParentID,
+ regInfo.RegistryIdentifier,
+ ).Return(registry, nil)
+ mockRegistryRepository.On(
+ "FetchUpstreamProxyIDs",
+ mock.Anything,
+ []string{regInfo.RegistryIdentifier},
+ regInfo.ParentID,
+ ).Return([]int64{}, nil)
+ mockUpstreamProxyStore.On("Delete", mock.Anything, regInfo.ParentID, regInfo.RegistryIdentifier).Return(nil)
+ mockImageStore.On("DeleteDownloadStatByRegistryID", mock.Anything, regInfo.RegistryID).Return(nil)
+ mockImageStore.On("DeleteBandwidthStatByRegistryID", mock.Anything, regInfo.RegistryID).Return(nil)
+ mockImageStore.On("DeleteByRegistryID", mock.Anything, regInfo.RegistryID).Return(nil)
+ mockRegistryRepository.On("Delete", mock.Anything, regInfo.ParentID, regInfo.RegistryIdentifier).Return(nil)
+ mockAuditService.On(
+ "Log",
+ mock.Anything,
+ mock.AnythingOfType("*types.PrincipalInfo"),
+ mock.AnythingOfType("*audit.Resource"),
+ mock.AnythingOfType("string"),
+ mock.AnythingOfType("string"),
+ mock.AnythingOfType("audit.Option"),
+ ).Return(nil)
+ // Simply return nil for the transaction - we're testing the controller logic, not transaction details
+ mockTx.On("WithTx", mock.Anything, mock.AnythingOfType("func(context.Context) error")).Return(nil)
+
+ c.SpaceFinder = mockSpaceFinder
+ c.RegistryRepository = mockRegistryRepository
+ c.Authorizer = mockAuthorizer
+ c.RegistryMetadataHelper = mockRegistryMetadataHelper
+ c.ImageStore = mockImageStore
+ c.tx = mockTx
+ c.AuditService = mockAuditService
+ c.UpstreamProxyStore = mockUpstreamProxyStore
+ },
+ request: api.DeleteRegistryRequestObject{
+ RegistryRef: "reg",
+ },
+ expectedResp: api.DeleteRegistry200JSONResponse{
+ SuccessJSONResponse: api.SuccessJSONResponse{
+ Status: api.StatusSUCCESS,
+ },
+ },
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ // Setup
+ controller := &APIController{}
+ tt.setupMocks(controller)
+
+ // Execute with the mock session context
+ resp, err := controller.DeleteRegistry(testCtx, tt.request)
+
+ // Verify error only if explicitly expected.
+ if tt.expectedError != nil {
+ assert.Error(t, err, "Expected an error but got none")
+ assert.Equal(t, tt.expectedError.Error(), err.Error(), "Error message should match")
+ } else if _, ok := tt.expectedResp.(api.DeleteRegistry200JSONResponse); ok {
+ // Only assert no error for success responses.
+ assert.NoError(t, err, "Expected no error for success response")
+ }
+ // For error response types like 400/404/403, we don't assert err since the response object is what matters.
+
+ // Verify response with detailed assertions.
+ assert.NotNil(t, resp, "Response should not be nil")
+
+ // Verify correct response type matching.
+ switch tt.expectedResp.(type) {
+ case api.DeleteRegistry200JSONResponse:
+ _, ok := resp.(api.DeleteRegistry200JSONResponse)
+ assert.True(t, ok, "Expected 200 success response")
+ // Not checking Status field as it's hardcoded in test data and doesn't validate behavior.
+
+ case api.DeleteRegistry400JSONResponse:
+ _, ok := resp.(api.DeleteRegistry400JSONResponse)
+ assert.True(t, ok, "Expected 400 bad request response")
+ // Not checking fields as they're hardcoded in test data.
+
+ case api.DeleteRegistry403JSONResponse:
+ _, ok := resp.(api.DeleteRegistry403JSONResponse)
+ assert.True(t, ok, "Expected 403 forbidden response")
+ // Not checking fields as they're hardcoded in test data.
+
+ case api.DeleteRegistry404JSONResponse:
+ _, ok := resp.(api.DeleteRegistry404JSONResponse)
+ assert.True(t, ok, "Expected 404 not found response")
+ // Not checking fields as they're hardcoded in test data.
+
+ default:
+ // Fallback to simple type equality for any other response types.
+ expectedType := fmt.Sprintf("%T", tt.expectedResp)
+ actualType := fmt.Sprintf("%T", resp)
+ assert.Equal(t, expectedType, actualType, "Response type should match.")
+ }
+
+ // Verify only essential mocks since we're not executing transaction functions.
+ if controller.SpaceFinder != nil {
+ mockSpaceFinder, ok := controller.SpaceFinder.(*mocks.SpaceFinder)
+ if !ok {
+ t.Fatal("Expected SpaceFinder to be of type *mocks.SpaceFinder")
+ }
+ mockSpaceFinder.AssertExpectations(t)
+ }
+
+ // Verify only FindByRef and GetPermissionChecks from RegistryRepository.
+ if controller.RegistryRepository != nil {
+ mockRegistryRepo, ok := controller.RegistryRepository.(*mocks.RegistryRepository)
+ if !ok {
+ t.Fatal("Expected RegistryRepository to be of type *mocks.RegistryRepository")
+ }
+ // We could use AssertCalled for specific methods if needed.
+ // Only verify GetByParentIDAndName which is called before the transaction.
+ mockRegistryRepo.AssertCalled(t, "GetByParentIDAndName", mock.Anything, mock.Anything, mock.Anything)
+ }
+
+ if controller.Authorizer != nil {
+ mockAuthorizer, ok := controller.Authorizer.(*mocks.Authorizer)
+ if !ok {
+ t.Fatal("Expected Authorizer to be of type *mocks.Authorizer")
+ }
+ mockAuthorizer.AssertExpectations(t)
+ }
+
+ if controller.RegistryMetadataHelper != nil {
+ mockRegistryMetadataHelper, ok := controller.RegistryMetadataHelper.(*mocks.RegistryMetadataHelper)
+ if !ok {
+ t.Fatal("Expected RegistryMetadataHelper to be of type *mocks.RegistryMetadataHelper")
+ }
+ mockRegistryMetadataHelper.AssertExpectations(t)
+ }
+
+ // Verify transaction was attempted.
+ if controller.tx != nil {
+ mockTx, ok := controller.tx.(*mocks.Transaction)
+ if !ok {
+ t.Fatal("Expected tx to be of type *mocks.Transaction")
+ }
+ mockTx.AssertCalled(t, "WithTx", mock.Anything, mock.Anything)
+ }
+ })
+ }
+}
diff --git a/registry/app/api/controller/metadata/get_artifact_detail.go b/registry/app/api/controller/metadata/get_artifact_detail.go
index 4e9aad17d..cdfa1a4b6 100644
--- a/registry/app/api/controller/metadata/get_artifact_detail.go
+++ b/registry/app/api/controller/metadata/get_artifact_detail.go
@@ -67,7 +67,7 @@ func (c *APIController) GetArtifactDetails(
image := string(r.Artifact)
version := string(r.Version)
- registry, err := c.RegistryRepository.GetByParentIDAndName(ctx, regInfo.parentID, regInfo.RegistryIdentifier)
+ registry, err := c.RegistryRepository.GetByParentIDAndName(ctx, regInfo.ParentID, regInfo.RegistryIdentifier)
if err != nil {
return artifact.GetArtifactDetails500JSONResponse{
diff --git a/registry/app/api/controller/metadata/get_artifact_files.go b/registry/app/api/controller/metadata/get_artifact_files.go
index 09385eedd..62abf031a 100644
--- a/registry/app/api/controller/metadata/get_artifact_files.go
+++ b/registry/app/api/controller/metadata/get_artifact_files.go
@@ -69,7 +69,7 @@ func (c *APIController) GetArtifactFiles(
image := string(r.Artifact)
version := string(r.Version)
- registry, err := c.RegistryRepository.GetByParentIDAndName(ctx, reqInfo.parentID, reqInfo.RegistryIdentifier)
+ registry, err := c.RegistryRepository.GetByParentIDAndName(ctx, reqInfo.ParentID, reqInfo.RegistryIdentifier)
if err != nil {
return artifact.GetArtifactFiles500JSONResponse{
diff --git a/registry/app/api/controller/metadata/get_artifacts.go b/registry/app/api/controller/metadata/get_artifacts.go
index 027d9f8a1..9b57b4ef3 100644
--- a/registry/app/api/controller/metadata/get_artifacts.go
+++ b/registry/app/api/controller/metadata/get_artifacts.go
@@ -76,11 +76,11 @@ func (c *APIController) GetAllArtifacts(
latestVersion = bool(*r.Params.LatestVersion)
}
artifacts, err := c.TagStore.GetAllArtifactsByParentID(
- ctx, regInfo.parentID, ®Info.registryIDs,
+ ctx, regInfo.ParentID, ®Info.registryIDs,
regInfo.sortByField, regInfo.sortByOrder, regInfo.limit, regInfo.offset, regInfo.searchTerm,
latestVersion, regInfo.packageTypes)
count, _ := c.TagStore.CountAllArtifactsByParentID(
- ctx, regInfo.parentID, ®Info.registryIDs,
+ ctx, regInfo.ParentID, ®Info.registryIDs,
regInfo.searchTerm, latestVersion, regInfo.packageTypes)
if err != nil {
return artifact.GetAllArtifacts500JSONResponse{
diff --git a/registry/app/api/controller/metadata/get_artifacts_docker_details.go b/registry/app/api/controller/metadata/get_artifacts_docker_details.go
index 85c7ff591..1831be9e4 100644
--- a/registry/app/api/controller/metadata/get_artifacts_docker_details.go
+++ b/registry/app/api/controller/metadata/get_artifacts_docker_details.go
@@ -72,7 +72,7 @@ func (c *APIController) GetDockerArtifactDetails(
version := string(r.Version)
manifestDigest := string(r.Params.Digest)
- registry, err := c.RegistryRepository.GetByParentIDAndName(ctx, regInfo.parentID, regInfo.RegistryIdentifier)
+ registry, err := c.RegistryRepository.GetByParentIDAndName(ctx, regInfo.ParentID, regInfo.RegistryIdentifier)
if err != nil {
return artifact.GetDockerArtifactDetails500JSONResponse{
diff --git a/registry/app/api/controller/metadata/get_artifacts_docker_layers.go b/registry/app/api/controller/metadata/get_artifacts_docker_layers.go
index ce2e93ede..17953a578 100644
--- a/registry/app/api/controller/metadata/get_artifacts_docker_layers.go
+++ b/registry/app/api/controller/metadata/get_artifacts_docker_layers.go
@@ -81,7 +81,7 @@ func (c *APIController) GetDockerArtifactLayers(
if err != nil {
return getLayersErrorResponse(ctx, err)
}
- registry, err := c.RegistryRepository.GetByParentIDAndName(ctx, regInfo.parentID, regInfo.RegistryIdentifier)
+ registry, err := c.RegistryRepository.GetByParentIDAndName(ctx, regInfo.ParentID, regInfo.RegistryIdentifier)
if err != nil {
return getLayersErrorResponse(ctx, err)
}
diff --git a/registry/app/api/controller/metadata/get_artifacts_docker_manifest.go b/registry/app/api/controller/metadata/get_artifacts_docker_manifest.go
index 280d8c516..0d701f96a 100644
--- a/registry/app/api/controller/metadata/get_artifacts_docker_manifest.go
+++ b/registry/app/api/controller/metadata/get_artifacts_docker_manifest.go
@@ -74,7 +74,7 @@ func (c *APIController) GetDockerArtifactManifest(
manifestPayload, err := c.ManifestStore.GetManifestPayload(
ctx,
- regInfo.parentID,
+ regInfo.ParentID,
regInfo.RegistryIdentifier,
imageName,
manifestDigest,
diff --git a/registry/app/api/controller/metadata/get_artifacts_docker_manifests.go b/registry/app/api/controller/metadata/get_artifacts_docker_manifests.go
index 52c62ad2b..6e06a40dd 100644
--- a/registry/app/api/controller/metadata/get_artifacts_docker_manifests.go
+++ b/registry/app/api/controller/metadata/get_artifacts_docker_manifests.go
@@ -92,10 +92,9 @@ func (c *APIController) GetDockerArtifactManifests(
}, nil
}
-func (c *APIController) getManifestList(
- ctx context.Context, reqManifest *ml.DeserializedManifestList, registry *types.Registry, image string,
- regInfo *RegistryRequestBaseInfo,
-) ([]artifact.DockerManifestDetails, error) {
+func (c *APIController) getManifestList(ctx context.Context, reqManifest *ml.DeserializedManifestList,
+ registry *types.Registry, image string, regInfo *types.RegistryRequestBaseInfo) (
+ []artifact.DockerManifestDetails, error) {
manifestDetailsList := []artifact.DockerManifestDetails{}
for _, manifestEntry := range reqManifest.Manifests {
dgst, err := types.NewDigest(manifestEntry.Digest)
@@ -169,10 +168,10 @@ func (c *APIController) getManifestDetails(
// of Docker manifest details.
func (c *APIController) ProcessManifest(
ctx context.Context,
- regInfo *RegistryRequestBaseInfo,
+ regInfo *types.RegistryRequestBaseInfo,
image, version string,
) ([]artifact.DockerManifestDetails, error) {
- registry, err := c.RegistryRepository.GetByParentIDAndName(ctx, regInfo.parentID, regInfo.RegistryIdentifier)
+ registry, err := c.RegistryRepository.GetByParentIDAndName(ctx, regInfo.ParentID, regInfo.RegistryIdentifier)
if err != nil {
return nil, err
}
diff --git a/registry/app/api/controller/metadata/get_artifacts_helm_details.go b/registry/app/api/controller/metadata/get_artifacts_helm_details.go
index d72ebfd7a..fe51ad858 100644
--- a/registry/app/api/controller/metadata/get_artifacts_helm_details.go
+++ b/registry/app/api/controller/metadata/get_artifacts_helm_details.go
@@ -67,7 +67,7 @@ func (c *APIController) GetHelmArtifactDetails(
image := string(r.Artifact)
version := string(r.Version)
- registry, err := c.RegistryRepository.GetByParentIDAndName(ctx, regInfo.parentID, regInfo.RegistryIdentifier)
+ registry, err := c.RegistryRepository.GetByParentIDAndName(ctx, regInfo.ParentID, regInfo.RegistryIdentifier)
if err != nil {
return artifact.GetHelmArtifactDetails500JSONResponse{
diff --git a/registry/app/api/controller/metadata/get_artifacts_helm_manifest.go b/registry/app/api/controller/metadata/get_artifacts_helm_manifest.go
index f76ce075b..4b7ed8a42 100644
--- a/registry/app/api/controller/metadata/get_artifacts_helm_manifest.go
+++ b/registry/app/api/controller/metadata/get_artifacts_helm_manifest.go
@@ -65,7 +65,7 @@ func (c *APIController) GetHelmArtifactManifest(
manifestPayload, err := c.ManifestStore.FindManifestPayloadByTagName(
ctx,
- regInfo.parentID,
+ regInfo.ParentID,
regInfo.RegistryIdentifier,
imageName,
version,
diff --git a/registry/app/api/controller/metadata/get_artifacts_labels.go b/registry/app/api/controller/metadata/get_artifacts_labels.go
index aa279b0a2..bf194bdf6 100644
--- a/registry/app/api/controller/metadata/get_artifacts_labels.go
+++ b/registry/app/api/controller/metadata/get_artifacts_labels.go
@@ -77,11 +77,11 @@ func (c *APIController) ListArtifactLabels(
}
labels, err := c.ImageStore.GetLabelsByParentIDAndRepo(
- ctx, regInfo.parentID,
+ ctx, regInfo.ParentID,
regInfo.RegistryIdentifier, regInfo.limit, regInfo.offset, regInfo.searchTerm,
)
count, _ := c.ImageStore.CountLabelsByParentIDAndRepo(
- ctx, regInfo.parentID,
+ ctx, regInfo.ParentID,
regInfo.RegistryIdentifier, regInfo.searchTerm,
)
diff --git a/registry/app/api/controller/metadata/get_artifacts_version_summary.go b/registry/app/api/controller/metadata/get_artifacts_version_summary.go
index 12f0eb40a..d402eff01 100644
--- a/registry/app/api/controller/metadata/get_artifacts_version_summary.go
+++ b/registry/app/api/controller/metadata/get_artifacts_version_summary.go
@@ -80,14 +80,14 @@ func (c *APIController) FetchArtifactSummary(
}
if registry.PackageType == artifact.PackageTypeDOCKER || registry.PackageType == artifact.PackageTypeHELM {
- tag, err := c.TagStore.GetTagMetadata(ctx, regInfo.parentID, regInfo.RegistryIdentifier, image, version)
+ tag, err := c.TagStore.GetTagMetadata(ctx, regInfo.ParentID, regInfo.RegistryIdentifier, image, version)
if err != nil {
return "", "", "", err
}
return image, tag.Name, tag.PackageType, nil
}
- artifact, err := c.ArtifactStore.GetArtifactMetadata(ctx, regInfo.parentID,
+ artifact, err := c.ArtifactStore.GetArtifactMetadata(ctx, regInfo.ParentID,
regInfo.RegistryIdentifier, image, version)
if err != nil {
diff --git a/registry/app/api/controller/metadata/get_artifacts_versions.go b/registry/app/api/controller/metadata/get_artifacts_versions.go
index 106166b12..797966863 100644
--- a/registry/app/api/controller/metadata/get_artifacts_versions.go
+++ b/registry/app/api/controller/metadata/get_artifacts_versions.go
@@ -89,7 +89,7 @@ func (c *APIController) GetAllArtifactVersions(
//nolint:nestif
if registry.PackageType == artifact.PackageTypeDOCKER || registry.PackageType == artifact.PackageTypeHELM {
tags, err := c.TagStore.GetAllTagsByRepoAndImage(
- ctx, regInfo.parentID, regInfo.RegistryIdentifier,
+ ctx, regInfo.ParentID, regInfo.RegistryIdentifier,
image, regInfo.sortByField, regInfo.sortByOrder, regInfo.limit, regInfo.offset, regInfo.searchTerm,
)
if err != nil {
@@ -114,7 +114,7 @@ func (c *APIController) GetAllArtifactVersions(
}
}
count, err := c.TagStore.CountAllTagsByRepoAndImage(
- ctx, regInfo.parentID, regInfo.RegistryIdentifier,
+ ctx, regInfo.ParentID, regInfo.RegistryIdentifier,
image, regInfo.searchTerm,
)
@@ -134,7 +134,7 @@ func (c *APIController) GetAllArtifactVersions(
}, nil
}
metadata, err := c.ArtifactStore.GetAllVersionsByRepoAndImage(
- ctx, regInfo.parentID, regInfo.RegistryIdentifier,
+ ctx, regInfo.ParentID, regInfo.RegistryIdentifier,
image, regInfo.sortByField, regInfo.sortByOrder, regInfo.limit, regInfo.offset, regInfo.searchTerm,
)
if err != nil {
@@ -142,7 +142,7 @@ func (c *APIController) GetAllArtifactVersions(
}
cnt, _ := c.ArtifactStore.CountAllVersionsByRepoAndImage(
- ctx, regInfo.parentID, regInfo.RegistryIdentifier,
+ ctx, regInfo.ParentID, regInfo.RegistryIdentifier,
image, regInfo.searchTerm,
)
@@ -164,6 +164,7 @@ func setDigestCount(ctx context.Context, tags []types.TagMetadata) error {
return nil
}
+//nolint:unused // kept for potential future use
func setDigestCountInTagMetadata(ctx context.Context, t *types.TagMetadata) error {
m := types.Manifest{
SchemaVersion: t.SchemaVersion,
@@ -188,6 +189,7 @@ func setDigestCountInTagMetadata(ctx context.Context, t *types.TagMetadata) erro
return nil
}
+//nolint:unused,unparam // kept for potential future use
func throw500Error(err error) (artifact.GetAllArtifactVersionsResponseObject, error) {
wrappedErr := fmt.Errorf("internal server error: %w", err)
return artifact.GetAllArtifactVersions500JSONResponse{
diff --git a/registry/app/api/controller/metadata/get_client_setup_details.go b/registry/app/api/controller/metadata/get_client_setup_details.go
index daf3a608b..a892ab3aa 100644
--- a/registry/app/api/controller/metadata/get_client_setup_details.go
+++ b/registry/app/api/controller/metadata/get_client_setup_details.go
@@ -25,6 +25,7 @@ import (
"github.com/harness/gitness/app/paths"
"github.com/harness/gitness/registry/app/api/openapi/contracts/artifact"
"github.com/harness/gitness/registry/app/common"
+ "github.com/harness/gitness/registry/utils"
"github.com/harness/gitness/types/enum"
"github.com/rs/zerolog/log"
@@ -65,7 +66,7 @@ func (c *APIController) GetClientSetupDetails(
}, nil
}
- reg, err := c.RegistryRepository.GetByParentIDAndName(ctx, regInfo.parentID, regInfo.RegistryIdentifier)
+ reg, err := c.RegistryRepository.GetByParentIDAndName(ctx, regInfo.ParentID, regInfo.RegistryIdentifier)
if err != nil {
return artifact.GetClientSetupDetails404JSONResponse{
NotFoundJSONResponse: artifact.NotFoundJSONResponse(
@@ -454,6 +455,7 @@ func (c *APIController) generateHelmClientSetupDetail(
}
}
+// TODO: Remove StringPtr / see why it is used.
func (c *APIController) generateMavenClientSetupDetail(
ctx context.Context,
artifactName *artifact.ArtifactParam,
@@ -466,62 +468,62 @@ func (c *APIController) generateMavenClientSetupDetail(
generateTokenStepType := artifact.ClientSetupStepTypeGenerateToken
section1 := artifact.ClientSetupSection{
- Header: stringPtr("1. Generate Identity Token"),
- SecHeader: stringPtr("An identity token will serve as the password for uploading and downloading artifacts."),
+ Header: utils.StringPtr("1. Generate Identity Token"),
+ SecHeader: utils.StringPtr("An identity token will serve as the password for uploading and downloading artifacts."),
}
_ = section1.FromClientSetupStepConfig(artifact.ClientSetupStepConfig{
Steps: &[]artifact.ClientSetupStep{
{
- Header: stringPtr("Generate an identity token"),
+ Header: utils.StringPtr("Generate an identity token"),
Type: &generateTokenStepType,
},
},
})
mavenSection1 := artifact.ClientSetupSection{
- Header: stringPtr("2. Pull a Maven Package"),
- SecHeader: stringPtr("Set default repository in your pom.xml file."),
+ Header: utils.StringPtr("2. Pull a Maven Package"),
+ SecHeader: utils.StringPtr("Set default repository in your pom.xml file."),
}
_ = mavenSection1.FromClientSetupStepConfig(artifact.ClientSetupStepConfig{
Steps: &[]artifact.ClientSetupStep{
{
- Header: stringPtr("To set default registry in your pom.xml file by adding the following:"),
+ Header: utils.StringPtr("To set default registry in your pom.xml file by adding the following:"),
Type: &staticStepType,
Commands: &[]artifact.ClientSetupStepCommand{
{
//nolint:lll
- Value: stringPtr("\n \n maven-dev\n /\n \n true\n always\n \n \n true\n always\n \n \n"),
+ Value: utils.StringPtr("\n \n maven-dev\n /\n \n true\n always\n \n \n true\n always\n \n \n"),
},
},
},
{
//nolint:lll
- Header: stringPtr("Copy the following your ~/ .m2/settings.xml file for MacOs, or $USERPROFILE$\\ .m2\\settings.xml for Windows to authenticate with token to pull from your Maven registry."),
+ Header: utils.StringPtr("Copy the following your ~/ .m2/settings.xml file for MacOs, or $USERPROFILE$\\ .m2\\settings.xml for Windows to authenticate with token to pull from your Maven registry."),
Type: &staticStepType,
Commands: &[]artifact.ClientSetupStepCommand{
{
//nolint:lll
- Value: stringPtr("\n \n \n maven-dev\n \n identity-token\n \n \n"),
+ Value: utils.StringPtr("\n \n \n maven-dev\n \n identity-token\n \n \n"),
},
},
},
{
//nolint:lll
- Header: stringPtr("Add a dependency to the project's pom.xml (replace , & with your own):"),
+ Header: utils.StringPtr("Add a dependency to the project's pom.xml (replace , & with your own):"),
Type: &staticStepType,
Commands: &[]artifact.ClientSetupStepCommand{
{
//nolint:lll
- Value: stringPtr("\n \n \n \n"),
+ Value: utils.StringPtr("\n \n \n \n"),
},
},
},
{
- Header: stringPtr("Install dependencies in pom.xml file"),
+ Header: utils.StringPtr("Install dependencies in pom.xml file"),
Type: &staticStepType,
Commands: &[]artifact.ClientSetupStepCommand{
{
- Value: stringPtr("mvn install"),
+ Value: utils.StringPtr("mvn install"),
},
},
},
@@ -529,39 +531,39 @@ func (c *APIController) generateMavenClientSetupDetail(
})
mavenSection2 := artifact.ClientSetupSection{
- Header: stringPtr("3. Push a Maven Package"),
- SecHeader: stringPtr("Set default repository in your pom.xml file."),
+ Header: utils.StringPtr("3. Push a Maven Package"),
+ SecHeader: utils.StringPtr("Set default repository in your pom.xml file."),
}
_ = mavenSection2.FromClientSetupStepConfig(artifact.ClientSetupStepConfig{
Steps: &[]artifact.ClientSetupStep{
{
- Header: stringPtr("To set default registry in your pom.xml file by adding the following:"),
+ Header: utils.StringPtr("To set default registry in your pom.xml file by adding the following:"),
Type: &staticStepType,
Commands: &[]artifact.ClientSetupStepCommand{
{
//nolint:lll
- Value: stringPtr("\n \n maven-dev\n /\n \n \n maven-dev\n /\n \n"),
+ Value: utils.StringPtr("\n \n maven-dev\n /\n \n \n maven-dev\n /\n \n"),
},
},
},
{
//nolint:lll
- Header: stringPtr("Copy the following your ~/ .m2/setting.xml file for MacOs, or $USERPROFILE$\\ .m2\\settings.xml for Windows to authenticate with token to push to your Maven registry."),
+ Header: utils.StringPtr("Copy the following your ~/ .m2/setting.xml file for MacOs, or $USERPROFILE$\\ .m2\\settings.xml for Windows to authenticate with token to push to your Maven registry."),
Type: &staticStepType,
Commands: &[]artifact.ClientSetupStepCommand{
{
//nolint:lll
- Value: stringPtr("\n \n \n maven-dev\n \n identity-token\n \n \n"),
+ Value: utils.StringPtr("\n \n \n maven-dev\n \n identity-token\n \n \n"),
},
},
},
{
- Header: stringPtr("Publish package to your Maven registry."),
+ Header: utils.StringPtr("Publish package to your Maven registry."),
Type: &staticStepType,
Commands: &[]artifact.ClientSetupStepCommand{
{
- Value: stringPtr("mvn deploy"),
+ Value: utils.StringPtr("mvn deploy"),
},
},
},
@@ -569,46 +571,46 @@ func (c *APIController) generateMavenClientSetupDetail(
})
gradleSection1 := artifact.ClientSetupSection{
- Header: stringPtr("2. Pull a Gradle Package"),
- SecHeader: stringPtr("Set default repository in your build.gradle file."),
+ Header: utils.StringPtr("2. Pull a Gradle Package"),
+ SecHeader: utils.StringPtr("Set default repository in your build.gradle file."),
}
_ = gradleSection1.FromClientSetupStepConfig(artifact.ClientSetupStepConfig{
Steps: &[]artifact.ClientSetupStep{
{
- Header: stringPtr("Set the default registry in your project’s build.gradle by adding the following:"),
+ Header: utils.StringPtr("Set the default registry in your project’s build.gradle by adding the following:"),
Type: &staticStepType,
Commands: &[]artifact.ClientSetupStepCommand{
{
//nolint:lll
- Value: stringPtr("repositories{\n maven{\n url \"/\"\n\n credentials {\n username \"\"\n password \"identity-token\"\n }\n }\n}"),
+ Value: utils.StringPtr("repositories{\n maven{\n url \"/\"\n\n credentials {\n username \"\"\n password \"identity-token\"\n }\n }\n}"),
},
},
},
{
//nolint:lll
- Header: stringPtr("As this is a private registry, you’ll need to authenticate. Create or add to the ~/.gradle/gradle.properties file with the following:"),
+ Header: utils.StringPtr("As this is a private registry, you’ll need to authenticate. Create or add to the ~/.gradle/gradle.properties file with the following:"),
Type: &staticStepType,
Commands: &[]artifact.ClientSetupStepCommand{
{
- Value: stringPtr("repositoryUser=\nrepositoryPassword={{identity-token}}"),
+ Value: utils.StringPtr("repositoryUser=\nrepositoryPassword={{identity-token}}"),
},
},
},
{
- Header: stringPtr("Add a dependency to the project’s build.gradle"),
+ Header: utils.StringPtr("Add a dependency to the project’s build.gradle"),
Type: &staticStepType,
Commands: &[]artifact.ClientSetupStepCommand{
{
- Value: stringPtr("dependencies {\n implementation '::'\n}"),
+ Value: utils.StringPtr("dependencies {\n implementation '::'\n}"),
},
},
},
{
- Header: stringPtr("Install dependencies in build.gradle file"),
+ Header: utils.StringPtr("Install dependencies in build.gradle file"),
Type: &staticStepType,
Commands: &[]artifact.ClientSetupStepCommand{
{
- Value: stringPtr("gradlew build // Linux or OSX\n gradlew.bat build // Windows"),
+ Value: utils.StringPtr("gradlew build // Linux or OSX\n gradlew.bat build // Windows"),
},
},
},
@@ -616,28 +618,28 @@ func (c *APIController) generateMavenClientSetupDetail(
})
gradleSection2 := artifact.ClientSetupSection{
- Header: stringPtr("3. Push a Gradle Package"),
- SecHeader: stringPtr("Set default repository in your build.gradle file."),
+ Header: utils.StringPtr("3. Push a Gradle Package"),
+ SecHeader: utils.StringPtr("Set default repository in your build.gradle file."),
}
_ = gradleSection2.FromClientSetupStepConfig(artifact.ClientSetupStepConfig{
Steps: &[]artifact.ClientSetupStep{
{
- Header: stringPtr("Add a maven publish plugin configuration to the project's build.gradle."),
+ Header: utils.StringPtr("Add a maven publish plugin configuration to the project's build.gradle."),
Type: &staticStepType,
Commands: &[]artifact.ClientSetupStepCommand{
{
//nolint:lll
- Value: stringPtr("publishing {\n publications {\n maven(MavenPublication) {\n groupId = 'GROUP_ID'\n artifactId = 'ARTIFACT_ID'\n version = 'VERSION'\n\n from components.java\n }\n }\n}"),
+ Value: utils.StringPtr("publishing {\n publications {\n maven(MavenPublication) {\n groupId = 'GROUP_ID'\n artifactId = 'ARTIFACT_ID'\n version = 'VERSION'\n\n from components.java\n }\n }\n}"),
},
},
},
{
- Header: stringPtr("Publish package to your Maven registry."),
+ Header: utils.StringPtr("Publish package to your Maven registry."),
Type: &staticStepType,
Commands: &[]artifact.ClientSetupStepCommand{
{
- Value: stringPtr("gradlew publish"),
+ Value: utils.StringPtr("gradlew publish"),
},
},
},
@@ -645,47 +647,47 @@ func (c *APIController) generateMavenClientSetupDetail(
})
sbtSection1 := artifact.ClientSetupSection{
- Header: stringPtr("2. Pull a Sbt/Scala Package"),
- SecHeader: stringPtr("Set default repository in your build.sbt file."),
+ Header: utils.StringPtr("2. Pull a Sbt/Scala Package"),
+ SecHeader: utils.StringPtr("Set default repository in your build.sbt file."),
}
_ = sbtSection1.FromClientSetupStepConfig(artifact.ClientSetupStepConfig{
Steps: &[]artifact.ClientSetupStep{
{
- Header: stringPtr("Set the default registry in your project’s build.sbt by adding the following:"),
+ Header: utils.StringPtr("Set the default registry in your project’s build.sbt by adding the following:"),
Type: &staticStepType,
Commands: &[]artifact.ClientSetupStepCommand{
{
//nolint:lll
- Value: stringPtr("resolver += \"Harness Registry\" at \"/\"\ncredentials += Credentials(Path.userHome / \".sbt\" / \".Credentials\")"),
+ Value: utils.StringPtr("resolver += \"Harness Registry\" at \"/\"\ncredentials += Credentials(Path.userHome / \".sbt\" / \".Credentials\")"),
},
},
},
{
//nolint:lll
- Header: stringPtr("As this is a private registry, you’ll need to authenticate. Create or add to the ~/.sbt/.credentials file with the following:"),
+ Header: utils.StringPtr("As this is a private registry, you’ll need to authenticate. Create or add to the ~/.sbt/.credentials file with the following:"),
Type: &staticStepType,
Commands: &[]artifact.ClientSetupStepCommand{
{
//nolint:lll
- Value: stringPtr("realm=Harness Registry\nhost=\nuser=\npassword={{identity-token}}"),
+ Value: utils.StringPtr("realm=Harness Registry\nhost=\nuser=\npassword={{identity-token}}"),
},
},
},
{
- Header: stringPtr("Add a dependency to the project’s build.sbt"),
+ Header: utils.StringPtr("Add a dependency to the project’s build.sbt"),
Type: &staticStepType,
Commands: &[]artifact.ClientSetupStepCommand{
{
- Value: stringPtr("libraryDependencies += \"\" % \"\" % \"\""),
+ Value: utils.StringPtr("libraryDependencies += \"\" % \"\" % \"\""),
},
},
},
{
- Header: stringPtr("Install dependencies in build.sbt file"),
+ Header: utils.StringPtr("Install dependencies in build.sbt file"),
Type: &staticStepType,
Commands: &[]artifact.ClientSetupStepCommand{
{
- Value: stringPtr("sbt update"),
+ Value: utils.StringPtr("sbt update"),
},
},
},
@@ -693,27 +695,27 @@ func (c *APIController) generateMavenClientSetupDetail(
})
sbtSection2 := artifact.ClientSetupSection{
- Header: stringPtr("3. Push a Sbt/Scala Package"),
- SecHeader: stringPtr("Set default repository in your build.sbt file."),
+ Header: utils.StringPtr("3. Push a Sbt/Scala Package"),
+ SecHeader: utils.StringPtr("Set default repository in your build.sbt file."),
}
_ = sbtSection2.FromClientSetupStepConfig(artifact.ClientSetupStepConfig{
Steps: &[]artifact.ClientSetupStep{
{
- Header: stringPtr("Add publish configuration to the project’s build.sbt."),
+ Header: utils.StringPtr("Add publish configuration to the project’s build.sbt."),
Type: &staticStepType,
Commands: &[]artifact.ClientSetupStepCommand{
{
- Value: stringPtr("publishTo := Some(\"Harness Registry\" at \"/\")"),
+ Value: utils.StringPtr("publishTo := Some(\"Harness Registry\" at \"/\")"),
},
},
},
{
- Header: stringPtr("Publish package to your Maven registry."),
+ Header: utils.StringPtr("Publish package to your Maven registry."),
Type: &staticStepType,
Commands: &[]artifact.ClientSetupStepCommand{
{
- Value: stringPtr("sbt publish"),
+ Value: utils.StringPtr("sbt publish"),
},
},
},
@@ -724,19 +726,19 @@ func (c *APIController) generateMavenClientSetupDetail(
config := artifact.TabSetupStepConfig{
Tabs: &[]artifact.TabSetupStep{
{
- Header: stringPtr("Maven"),
+ Header: utils.StringPtr("Maven"),
Sections: &[]artifact.ClientSetupSection{
mavenSection1,
},
},
{
- Header: stringPtr("Gradle"),
+ Header: utils.StringPtr("Gradle"),
Sections: &[]artifact.ClientSetupSection{
gradleSection1,
},
},
{
- Header: stringPtr("Sbt/Scala"),
+ Header: utils.StringPtr("Sbt/Scala"),
Sections: &[]artifact.ClientSetupSection{
sbtSection1,
},
@@ -794,16 +796,16 @@ func (c *APIController) generatePythonClientSetupDetail(
// Authentication section
section1 := artifact.ClientSetupSection{
- Header: stringPtr("Configure Authentication"),
+ Header: utils.StringPtr("Configure Authentication"),
}
_ = section1.FromClientSetupStepConfig(artifact.ClientSetupStepConfig{
Steps: &[]artifact.ClientSetupStep{
{
- Header: stringPtr("Create or update your ~/.pypirc file with the following content:"),
+ Header: utils.StringPtr("Create or update your ~/.pypirc file with the following content:"),
Type: &staticStepType,
Commands: &[]artifact.ClientSetupStepCommand{
{
- Value: stringPtr("[distutils]\n" +
+ Value: utils.StringPtr("[distutils]\n" +
"index-servers = harness\n\n" +
"[harness]\n" +
"repository = \n" +
@@ -813,7 +815,7 @@ func (c *APIController) generatePythonClientSetupDetail(
},
},
{
- Header: stringPtr("Generate an identity token for authentication"),
+ Header: utils.StringPtr("Generate an identity token for authentication"),
Type: &generateTokenType,
},
},
@@ -821,19 +823,19 @@ func (c *APIController) generatePythonClientSetupDetail(
// Publish section
section2 := artifact.ClientSetupSection{
- Header: stringPtr("Publish Package"),
+ Header: utils.StringPtr("Publish Package"),
}
_ = section2.FromClientSetupStepConfig(artifact.ClientSetupStepConfig{
Steps: &[]artifact.ClientSetupStep{
{
- Header: stringPtr("Build and publish your package:"),
+ Header: utils.StringPtr("Build and publish your package:"),
Type: &staticStepType,
Commands: &[]artifact.ClientSetupStepCommand{
{
- Value: stringPtr("python -m build"),
+ Value: utils.StringPtr("python -m build"),
},
{
- Value: stringPtr("python -m twine upload --repository harness /path/to/files/*"),
+ Value: utils.StringPtr("python -m twine upload --repository harness /path/to/files/*"),
},
},
},
@@ -842,16 +844,16 @@ func (c *APIController) generatePythonClientSetupDetail(
// Install section
section3 := artifact.ClientSetupSection{
- Header: stringPtr("Install Package"),
+ Header: utils.StringPtr("Install Package"),
}
_ = section3.FromClientSetupStepConfig(artifact.ClientSetupStepConfig{
Steps: &[]artifact.ClientSetupStep{
{
- Header: stringPtr("Install a package using pip:"),
+ Header: utils.StringPtr("Install a package using pip:"),
Type: &staticStepType,
Commands: &[]artifact.ClientSetupStepCommand{
{
- Value: stringPtr("pip install --index-url /simple --no-deps =="),
+ Value: utils.StringPtr("pip install --index-url /simple --no-deps =="),
},
},
},
@@ -901,24 +903,24 @@ func (c *APIController) generateNpmClientSetupDetail(
// Authentication section
section1 := artifact.ClientSetupSection{
- Header: stringPtr("Configure Authentication"),
+ Header: utils.StringPtr("Configure Authentication"),
}
_ = section1.FromClientSetupStepConfig(artifact.ClientSetupStepConfig{
Steps: &[]artifact.ClientSetupStep{
{
- Header: stringPtr("Create or update your ~/.npmrc file with the following content:"),
+ Header: utils.StringPtr("Create or update your ~/.npmrc file with the following content:"),
Type: &staticStepType,
Commands: &[]artifact.ClientSetupStepCommand{
{
- Value: stringPtr("https:/"),
+ Value: utils.StringPtr("https:/"),
},
{
- Value: stringPtr("/:_authToken "),
+ Value: utils.StringPtr("/:_authToken "),
},
},
},
{
- Header: stringPtr("Generate an identity token for authentication"),
+ Header: utils.StringPtr("Generate an identity token for authentication"),
Type: &generateTokenType,
},
},
@@ -926,19 +928,19 @@ func (c *APIController) generateNpmClientSetupDetail(
// Publish section
section2 := artifact.ClientSetupSection{
- Header: stringPtr("Publish Package"),
+ Header: utils.StringPtr("Publish Package"),
}
_ = section2.FromClientSetupStepConfig(artifact.ClientSetupStepConfig{
Steps: &[]artifact.ClientSetupStep{
{
- Header: stringPtr("Build and publish your package:"),
+ Header: utils.StringPtr("Build and publish your package:"),
Type: &staticStepType,
Commands: &[]artifact.ClientSetupStepCommand{
{
- Value: stringPtr("npm init -y\n"),
+ Value: utils.StringPtr("npm run build\n"),
},
{
- Value: stringPtr("npm publish"),
+ Value: utils.StringPtr("npm publish"),
},
},
},
@@ -947,16 +949,16 @@ func (c *APIController) generateNpmClientSetupDetail(
// Install section
section3 := artifact.ClientSetupSection{
- Header: stringPtr("Install Package"),
+ Header: utils.StringPtr("Install Package"),
}
_ = section3.FromClientSetupStepConfig(artifact.ClientSetupStepConfig{
Steps: &[]artifact.ClientSetupStep{
{
- Header: stringPtr("Install a package using npm"),
+ Header: utils.StringPtr("Install a package using npm"),
Type: &staticStepType,
Commands: &[]artifact.ClientSetupStepCommand{
{
- Value: stringPtr("npm install @"),
+ Value: utils.StringPtr("npm install @"),
},
},
},
@@ -1078,44 +1080,40 @@ func replaceText(
uploadURL string,
) {
if username != "" {
- (*st.Commands)[i].Value = stringPtr(strings.ReplaceAll(*(*st.Commands)[i].Value, "", username))
+ (*st.Commands)[i].Value = utils.StringPtr(strings.ReplaceAll(*(*st.Commands)[i].Value, "", username))
if (*st.Commands)[i].Label != nil {
- (*st.Commands)[i].Label = stringPtr(strings.ReplaceAll(*(*st.Commands)[i].Label, "", username))
+ (*st.Commands)[i].Label = utils.StringPtr(strings.ReplaceAll(*(*st.Commands)[i].Label, "", username))
}
}
if groupID != "" {
- (*st.Commands)[i].Value = stringPtr(strings.ReplaceAll(*(*st.Commands)[i].Value, "", groupID))
+ (*st.Commands)[i].Value = utils.StringPtr(strings.ReplaceAll(*(*st.Commands)[i].Value, "", groupID))
}
if registryURL != "" {
- (*st.Commands)[i].Value = stringPtr(strings.ReplaceAll(*(*st.Commands)[i].Value, "", registryURL))
+ (*st.Commands)[i].Value = utils.StringPtr(strings.ReplaceAll(*(*st.Commands)[i].Value, "", registryURL))
}
if uploadURL != "" {
- (*st.Commands)[i].Value = stringPtr(strings.ReplaceAll(*(*st.Commands)[i].Value, "", uploadURL))
+ (*st.Commands)[i].Value = utils.StringPtr(strings.ReplaceAll(*(*st.Commands)[i].Value, "", uploadURL))
}
if hostname != "" {
- (*st.Commands)[i].Value = stringPtr(strings.ReplaceAll(*(*st.Commands)[i].Value, "", hostname))
+ (*st.Commands)[i].Value = utils.StringPtr(strings.ReplaceAll(*(*st.Commands)[i].Value, "", hostname))
}
if hostname != "" {
- (*st.Commands)[i].Value = stringPtr(strings.ReplaceAll(*(*st.Commands)[i].Value,
+ (*st.Commands)[i].Value = utils.StringPtr(strings.ReplaceAll(*(*st.Commands)[i].Value,
"", common.GetHost(hostname)))
}
if repoName != "" {
- (*st.Commands)[i].Value = stringPtr(strings.ReplaceAll(*(*st.Commands)[i].Value, "", repoName))
+ (*st.Commands)[i].Value = utils.StringPtr(strings.ReplaceAll(*(*st.Commands)[i].Value, "", repoName))
}
if image != nil {
- (*st.Commands)[i].Value = stringPtr(strings.ReplaceAll(*(*st.Commands)[i].Value, "",
+ (*st.Commands)[i].Value = utils.StringPtr(strings.ReplaceAll(*(*st.Commands)[i].Value, "",
string(*image)))
- (*st.Commands)[i].Value = stringPtr(strings.ReplaceAll(*(*st.Commands)[i].Value, "",
+ (*st.Commands)[i].Value = utils.StringPtr(strings.ReplaceAll(*(*st.Commands)[i].Value, "",
string(*image)))
- (*st.Commands)[i].Value = stringPtr(strings.ReplaceAll(*(*st.Commands)[i].Value, "",
+ (*st.Commands)[i].Value = utils.StringPtr(strings.ReplaceAll(*(*st.Commands)[i].Value, "",
string(*image)))
}
if tag != nil {
- (*st.Commands)[i].Value = stringPtr(strings.ReplaceAll(*(*st.Commands)[i].Value, "", string(*tag)))
- (*st.Commands)[i].Value = stringPtr(strings.ReplaceAll(*(*st.Commands)[i].Value, "", string(*tag)))
+ (*st.Commands)[i].Value = utils.StringPtr(strings.ReplaceAll(*(*st.Commands)[i].Value, "", string(*tag)))
+ (*st.Commands)[i].Value = utils.StringPtr(strings.ReplaceAll(*(*st.Commands)[i].Value, "", string(*tag)))
}
}
-
-func stringPtr(s string) *string {
- return &s
-}
diff --git a/registry/app/api/controller/metadata/get_registries.go b/registry/app/api/controller/metadata/get_registries.go
index ec67d2e22..b30585926 100644
--- a/registry/app/api/controller/metadata/get_registries.go
+++ b/registry/app/api/controller/metadata/get_registries.go
@@ -96,7 +96,7 @@ func (c *APIController) GetAllRegistries(
var count int64
repos, err = c.RegistryRepository.GetAll(
ctx,
- regInfo.parentID,
+ regInfo.ParentID,
regInfo.packageTypes,
regInfo.sortByField,
regInfo.sortByOrder,
@@ -108,7 +108,7 @@ func (c *APIController) GetAllRegistries(
)
count, _ = c.RegistryRepository.CountAll(
ctx,
- regInfo.parentID,
+ regInfo.ParentID,
regInfo.packageTypes,
regInfo.searchTerm,
repoType,
diff --git a/registry/app/api/controller/metadata/get_registry.go b/registry/app/api/controller/metadata/get_registry.go
index 9f153cc3b..e28f4dbeb 100644
--- a/registry/app/api/controller/metadata/get_registry.go
+++ b/registry/app/api/controller/metadata/get_registry.go
@@ -60,7 +60,7 @@ func (c *APIController) GetRegistry(
),
}, nil
}
- repoEntity, _ := c.RegistryRepository.GetByParentIDAndName(ctx, regInfo.parentID, regInfo.RegistryIdentifier)
+ repoEntity, _ := c.RegistryRepository.GetByParentIDAndName(ctx, regInfo.ParentID, regInfo.RegistryIdentifier)
if string(repoEntity.Type) == string(artifact.RegistryTypeVIRTUAL) {
cleanupPolicies, err := c.CleanupPolicyStore.GetByRegistryID(ctx, repoEntity.ID)
if err != nil {
@@ -84,7 +84,7 @@ func (c *APIController) GetRegistry(
}
upstreamproxyEntity, err := c.UpstreamProxyStore.GetByRegistryIdentifier(
ctx,
- regInfo.parentID, regInfo.RegistryIdentifier,
+ regInfo.ParentID, regInfo.RegistryIdentifier,
)
if len(upstreamproxyEntity.RepoKey) == 0 {
return artifact.GetRegistry404JSONResponse{
diff --git a/registry/app/api/controller/metadata/get_registry_artifacts.go b/registry/app/api/controller/metadata/get_registry_artifacts.go
index e5eb38264..dba4d7c41 100644
--- a/registry/app/api/controller/metadata/get_registry_artifacts.go
+++ b/registry/app/api/controller/metadata/get_registry_artifacts.go
@@ -85,11 +85,11 @@ func (c *APIController) GetAllArtifactsByRegistry(
var count int64
if registry.PackageType == artifact.PackageTypeDOCKER || registry.PackageType == artifact.PackageTypeHELM {
artifacts, err = c.TagStore.GetAllArtifactsByRepo(
- ctx, regInfo.parentID, regInfo.RegistryIdentifier,
+ ctx, regInfo.ParentID, regInfo.RegistryIdentifier,
regInfo.sortByField, regInfo.sortByOrder, regInfo.limit, regInfo.offset, regInfo.searchTerm, regInfo.labels,
)
count, _ = c.TagStore.CountAllArtifactsByRepo(
- ctx, regInfo.parentID, regInfo.RegistryIdentifier,
+ ctx, regInfo.ParentID, regInfo.RegistryIdentifier,
regInfo.searchTerm, regInfo.labels,
)
if err != nil {
@@ -101,10 +101,10 @@ func (c *APIController) GetAllArtifactsByRegistry(
}
} else {
artifacts, err = c.ArtifactStore.GetArtifactsByRepo(
- ctx, regInfo.parentID, regInfo.RegistryIdentifier,
+ ctx, regInfo.ParentID, regInfo.RegistryIdentifier,
regInfo.sortByField, regInfo.sortByOrder, regInfo.limit, regInfo.offset, regInfo.searchTerm, regInfo.labels)
count, _ = c.ArtifactStore.CountArtifactsByRepo(
- ctx, regInfo.parentID, regInfo.RegistryIdentifier,
+ ctx, regInfo.ParentID, regInfo.RegistryIdentifier,
regInfo.searchTerm, regInfo.labels)
if err != nil {
return artifact.GetAllArtifactsByRegistry500JSONResponse{
diff --git a/registry/app/api/controller/metadata/get_webhook_execution_test.go b/registry/app/api/controller/metadata/get_webhook_execution_test.go
index 9b138c10b..83c549faf 100644
--- a/registry/app/api/controller/metadata/get_webhook_execution_test.go
+++ b/registry/app/api/controller/metadata/get_webhook_execution_test.go
@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+//nolint:lll
package metadata
import (
@@ -20,239 +21,262 @@ import (
"testing"
"time"
+ "github.com/harness/gitness/app/auth"
+ "github.com/harness/gitness/registry/app/api/controller/mocks"
api "github.com/harness/gitness/registry/app/api/openapi/contracts/artifact"
- gitnesstypes "github.com/harness/gitness/types"
+ "github.com/harness/gitness/registry/types"
+ coretypes "github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
-//nolint:errcheck
-func TestGetWebhookExecution_Success(t *testing.T) {
- ctx := context.Background()
- mockSpaceFinder := new(MockSpaceFinder)
- mockRegistryRepository := new(MockRegistryRepository)
- mockWebhooksRepository := new(MockWebhooksRepository)
- mockWebhooksExecutionRepository := new(MockWebhooksExecutionRepository)
- mockAuthorizer := new(MockAuthorizer)
- mockRegistryMetadataHelper := new(MockRegistryMetadataHelper)
- controller := &APIController{
- SpaceFinder: mockSpaceFinder,
- RegistryRepository: mockRegistryRepository,
- WebhooksRepository: mockWebhooksRepository,
- WebhooksExecutionRepository: mockWebhooksExecutionRepository,
- Authorizer: mockAuthorizer,
- RegistryMetadataHelper: mockRegistryMetadataHelper,
- }
+func TestGetWebhookExecution(t *testing.T) {
+ now := time.Now().Unix()
+ tests := []struct {
+ name string
+ setupMocks func(
+ *APIController,
+ *mocks.SpaceFinder,
+ *mocks.Authorizer,
+ *mocks.RegistryMetadataHelper,
+ *mocks.WebhooksRepository,
+ *mocks.WebhooksExecutionRepository)
+ request api.GetWebhookExecutionRequestObject
+ validate func(*testing.T, api.GetWebhookExecutionResponseObject, error)
+ }{
+ {
+ name: "invalid_execution_identifier",
+ setupMocks: func(c *APIController, mockSpaceFinder *mocks.SpaceFinder, mockAuthorizer *mocks.Authorizer, mockRegistryMetadataHelper *mocks.RegistryMetadataHelper, mockWebhooksRepo *mocks.WebhooksRepository, mockWebhooksExecRepo *mocks.WebhooksExecutionRepository) {
+ space := &coretypes.SpaceCore{ID: 2}
+ regInfo := &types.RegistryRequestBaseInfo{
+ RegistryID: 1,
+ RegistryIdentifier: "reg",
+ ParentID: 2,
+ ParentRef: "root/parent",
+ }
- regInfo := &RegistryRequestBaseInfo{
- RegistryID: 1,
- RegistryIdentifier: "reg",
- ParentRef: "root/parent",
- }
- space := &gitnesstypes.SpaceCore{ID: 2}
- var permissionChecks []gitnesstypes.PermissionCheck
- mockRegistryMetadataHelper.On("GetRegistryRequestBaseInfo", ctx, "", "reg").Return(regInfo, nil)
- mockSpaceFinder.On("FindByRef", ctx, "root/parent").Return(space, nil)
- mockRegistryMetadataHelper.On("GetPermissionChecks", space,
- regInfo.RegistryIdentifier, enum.PermissionRegistryView).Return(permissionChecks)
- mockAuthorizer.On("CheckAll", ctx, mock.Anything, permissionChecks).Return(true, nil)
- mockWebhooksExecutionRepository.On("Find", ctx, int64(1)).Return(&gitnesstypes.WebhookExecutionCore{
- ID: 1,
- Created: time.Now().Unix(),
- Duration: 100,
- Error: "none",
- Request: gitnesstypes.WebhookExecutionRequest{
- Body: "{}", Headers: "headers", URL: "http://example.com",
+ mockSpaceFinder.On("FindByRef", mock.Anything, "root/parent").Return(space, nil)
+ mockRegistryMetadataHelper.On("GetRegistryRequestBaseInfo", mock.Anything, "", "reg").Return(regInfo, nil)
+ mockRegistryMetadataHelper.On("GetPermissionChecks", space, "reg", enum.PermissionRegistryView).Return([]coretypes.PermissionCheck{})
+ mockAuthorizer.On("CheckAll", mock.Anything, (*auth.Session)(nil), mock.Anything).Return(true, nil)
+
+ c.SpaceFinder = mockSpaceFinder
+ c.Authorizer = mockAuthorizer
+ c.RegistryMetadataHelper = mockRegistryMetadataHelper
+ c.WebhooksRepository = mockWebhooksRepo
+ c.WebhooksExecutionRepository = mockWebhooksExecRepo
+ },
+ request: api.GetWebhookExecutionRequestObject{
+ RegistryRef: "reg",
+ WebhookIdentifier: "webhook",
+ WebhookExecutionId: "invalid",
+ },
+ validate: func(t *testing.T, response api.GetWebhookExecutionResponseObject, err error) {
+ assert.NoError(t, err)
+ assert.NotNil(t, response)
+
+ resp, ok := response.(api.GetWebhookExecution400JSONResponse)
+ assert.True(t, ok, "expected 400 response")
+ assert.Equal(t, "400", resp.Code)
+ assert.Equal(t, "invalid webhook execution identifier: invalid, err: strconv.ParseInt: parsing \"invalid\": invalid syntax", resp.Message)
+ },
},
- Response: gitnesstypes.WebhookExecutionResponse{
- Body: "{}", Headers: "headers", Status: "200 OK", StatusCode: 200,
+ {
+ name: "permission_check_fails",
+ setupMocks: func(c *APIController, mockSpaceFinder *mocks.SpaceFinder, mockAuthorizer *mocks.Authorizer, mockRegistryMetadataHelper *mocks.RegistryMetadataHelper, mockWebhooksRepo *mocks.WebhooksRepository, mockWebhooksExecRepo *mocks.WebhooksExecutionRepository) {
+ space := &coretypes.SpaceCore{ID: 2}
+ regInfo := &types.RegistryRequestBaseInfo{
+ RegistryID: 1,
+ RegistryIdentifier: "reg",
+ ParentID: 2,
+ ParentRef: "root/parent",
+ }
+
+ mockSpaceFinder.On("FindByRef", mock.Anything, "root/parent").Return(space, nil)
+ mockRegistryMetadataHelper.On("GetRegistryRequestBaseInfo", mock.Anything, "", "reg").Return(regInfo, nil)
+ mockRegistryMetadataHelper.On("GetPermissionChecks", space, "reg", enum.PermissionRegistryView).Return([]coretypes.PermissionCheck{})
+ mockAuthorizer.On("CheckAll", mock.Anything, mock.Anything, mock.Anything).Return(false, nil)
+
+ c.SpaceFinder = mockSpaceFinder
+ c.Authorizer = mockAuthorizer
+ c.RegistryMetadataHelper = mockRegistryMetadataHelper
+ c.WebhooksRepository = mockWebhooksRepo
+ c.WebhooksExecutionRepository = mockWebhooksExecRepo
+ },
+ request: api.GetWebhookExecutionRequestObject{
+ RegistryRef: "reg",
+ WebhookIdentifier: "webhook",
+ WebhookExecutionId: "1",
+ },
+ validate: func(t *testing.T, response api.GetWebhookExecutionResponseObject, err error) {
+ assert.NoError(t, err)
+ assert.NotNil(t, response)
+
+ resp, ok := response.(api.GetWebhookExecution403JSONResponse)
+ assert.True(t, ok, "expected 403 response")
+ assert.Equal(t, "403", resp.Code)
+ assert.Equal(t, "forbidden", resp.Message)
+ },
},
- RetriggerOf: nil,
- Retriggerable: true,
- WebhookID: 4,
- Result: enum.WebhookExecutionResultSuccess,
- TriggerType: enum.WebhookTriggerArtifactCreated}, nil)
+ {
+ name: "success_case",
+ setupMocks: func(c *APIController, mockSpaceFinder *mocks.SpaceFinder, mockAuthorizer *mocks.Authorizer, mockRegistryMetadataHelper *mocks.RegistryMetadataHelper, mockWebhooksRepo *mocks.WebhooksRepository, mockWebhooksExecRepo *mocks.WebhooksExecutionRepository) {
+ space := &coretypes.SpaceCore{ID: 2}
+ regInfo := &types.RegistryRequestBaseInfo{
+ RegistryID: 1,
+ RegistryIdentifier: "reg",
+ ParentID: 2,
+ ParentRef: "root/parent",
+ }
- r := api.GetWebhookExecutionRequestObject{
- RegistryRef: "reg",
- WebhookIdentifier: "webhook",
- WebhookExecutionId: "1",
+ execution := &coretypes.WebhookExecutionCore{
+ ID: 1,
+ Created: now,
+ WebhookID: 1,
+ Result: enum.WebhookExecutionResultSuccess,
+ Duration: 0,
+ Error: "",
+ Retriggerable: false,
+ Request: coretypes.WebhookExecutionRequest{
+ URL: "http://example.com",
+ Headers: "{}",
+ Body: "{}",
+ },
+ Response: coretypes.WebhookExecutionResponse{
+ StatusCode: 200,
+ Status: "OK",
+ Headers: "{}",
+ Body: "{}",
+ },
+ }
+
+ mockSpaceFinder.On("FindByRef", mock.Anything, "root/parent").Return(space, nil)
+ mockRegistryMetadataHelper.On("GetRegistryRequestBaseInfo", mock.Anything, "", "reg").Return(regInfo, nil)
+ mockRegistryMetadataHelper.On("GetPermissionChecks", space, "reg", enum.PermissionRegistryView).Return([]coretypes.PermissionCheck{})
+ mockAuthorizer.On("CheckAll", mock.Anything, (*auth.Session)(nil)).Return(true, nil)
+ mockWebhooksExecRepo.On("Find", mock.Anything, int64(1)).Return(execution, nil)
+
+ c.SpaceFinder = mockSpaceFinder
+ c.Authorizer = mockAuthorizer
+ c.RegistryMetadataHelper = mockRegistryMetadataHelper
+ c.WebhooksRepository = mockWebhooksRepo
+ c.WebhooksExecutionRepository = mockWebhooksExecRepo
+ },
+ request: api.GetWebhookExecutionRequestObject{
+ RegistryRef: "reg",
+ WebhookIdentifier: "webhook",
+ WebhookExecutionId: "1",
+ },
+ validate: func(t *testing.T, response api.GetWebhookExecutionResponseObject, err error) {
+ assert.NoError(t, err)
+ assert.NotNil(t, response)
+
+ resp, ok := response.(api.GetWebhookExecution200JSONResponse)
+ assert.True(t, ok, "expected 200 response")
+ assert.Equal(t, api.StatusSUCCESS, resp.Status)
+
+ exec := resp.Data
+ assert.Equal(t, int64(1), *exec.Id)
+ assert.Equal(t, now, *exec.Created)
+ assert.Equal(t, int64(1), *exec.WebhookId)
+ assert.Equal(t, api.WebhookExecResultSUCCESS, *exec.Result)
+ assert.Equal(t, int64(0), *exec.Duration)
+ assert.Equal(t, "", *exec.Error)
+ assert.False(t, *exec.Retriggerable)
+
+ assert.Equal(t, "http://example.com", *exec.Request.Url)
+ assert.Equal(t, "{}", *exec.Request.Headers)
+ assert.Equal(t, "{}", *exec.Request.Body)
+
+ assert.Equal(t, 200, *exec.Response.StatusCode)
+ assert.Equal(t, "OK", *exec.Response.Status)
+ assert.Equal(t, "{}", *exec.Response.Headers)
+ assert.Equal(t, "{}", *exec.Response.Body)
+ },
+ },
+ {
+ name: "find_execution_error",
+ setupMocks: func(c *APIController, mockSpaceFinder *mocks.SpaceFinder, mockAuthorizer *mocks.Authorizer, mockRegistryMetadataHelper *mocks.RegistryMetadataHelper, mockWebhooksRepo *mocks.WebhooksRepository, mockWebhooksExecRepo *mocks.WebhooksExecutionRepository) {
+ space := &coretypes.SpaceCore{ID: 2}
+ regInfo := &types.RegistryRequestBaseInfo{
+ RegistryID: 1,
+ RegistryIdentifier: "reg",
+ ParentID: 2,
+ ParentRef: "root/parent",
+ }
+
+ mockSpaceFinder.On("FindByRef", mock.Anything, "root/parent").Return(space, nil)
+ mockRegistryMetadataHelper.On(
+ "GetRegistryRequestBaseInfo",
+ mock.Anything,
+ "",
+ "reg",
+ ).Return(regInfo, nil)
+ mockRegistryMetadataHelper.On(
+ "GetPermissionChecks",
+ space,
+ "reg",
+ enum.PermissionRegistryView,
+ ).Return([]coretypes.PermissionCheck{})
+ mockAuthorizer.On("CheckAll", mock.Anything, mock.Anything, mock.Anything).Return(true, nil)
+ mockWebhooksExecRepo.On(
+ "Find",
+ mock.Anything,
+ int64(1),
+ ).Return(nil, fmt.Errorf("error finding execution"))
+
+ c.SpaceFinder = mockSpaceFinder
+ c.Authorizer = mockAuthorizer
+ c.RegistryMetadataHelper = mockRegistryMetadataHelper
+ c.WebhooksRepository = mockWebhooksRepo
+ c.WebhooksExecutionRepository = mockWebhooksExecRepo
+ },
+ request: api.GetWebhookExecutionRequestObject{
+ RegistryRef: "reg",
+ WebhookIdentifier: "webhook",
+ WebhookExecutionId: "1",
+ },
+ validate: func(t *testing.T, response api.GetWebhookExecutionResponseObject, err error) {
+ assert.NoError(t, err)
+ assert.NotNil(t, response)
+
+ resp, ok := response.(api.GetWebhookExecution500JSONResponse)
+ assert.True(t, ok, "expected 500 response")
+ assert.Equal(t, "500", resp.Code)
+ assert.Equal(t, "failed to find webhook execution: error finding execution", resp.Message)
+ },
+ },
}
- response, err := controller.GetWebhookExecution(ctx, r)
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ // Create mocks
+ mockSpaceFinder := new(mocks.SpaceFinder)
+ mockAuthorizer := new(mocks.Authorizer)
+ mockRegistryMetadataHelper := new(mocks.RegistryMetadataHelper)
+ mockWebhooksRepo := new(mocks.WebhooksRepository)
+ mockWebhooksExecRepo := new(mocks.WebhooksExecutionRepository)
- assert.NoError(t, err)
- assert.NotNil(t, response)
- assert.Equal(t, api.StatusSUCCESS, response.(api.GetWebhookExecution200JSONResponse).Status)
- assert.Equal(t, int64(1), *response.(api.GetWebhookExecution200JSONResponse).Data.Id)
- assert.Equal(t, "none", *response.(api.GetWebhookExecution200JSONResponse).Data.Error)
- assert.Equal(t, "{}", *response.(api.GetWebhookExecution200JSONResponse).Data.Request.Body)
- assert.Equal(t, "headers", *response.(api.GetWebhookExecution200JSONResponse).Data.Request.Headers)
- assert.Equal(t, "http://example.com", *response.(api.GetWebhookExecution200JSONResponse).Data.Request.Url)
- assert.Equal(t, "{}", *response.(api.GetWebhookExecution200JSONResponse).Data.Response.Body)
- assert.Equal(t, "headers", *response.(api.GetWebhookExecution200JSONResponse).Data.Response.Headers)
- assert.Equal(t, "200 OK", *response.(api.GetWebhookExecution200JSONResponse).Data.Response.Status)
- assert.Equal(t, 200, *response.(api.GetWebhookExecution200JSONResponse).Data.Response.StatusCode)
- assert.Equal(t, api.WebhookExecResultSUCCESS, *response.(api.GetWebhookExecution200JSONResponse).Data.Result)
- assert.Equal(t, api.TriggerARTIFACTCREATION, *response.(api.GetWebhookExecution200JSONResponse).Data.TriggerType)
- assert.Equal(t, api.StatusSUCCESS, response.(api.GetWebhookExecution200JSONResponse).Status)
+ // Create controller
+ controller := &APIController{}
- mockRegistryMetadataHelper.AssertExpectations(t)
- mockSpaceFinder.AssertExpectations(t)
- mockAuthorizer.AssertExpectations(t)
- mockWebhooksExecutionRepository.AssertExpectations(t)
-}
-
-//nolint:errcheck
-func TestGetWebhookExecution_PermissionCheckFails(t *testing.T) {
- ctx := context.Background()
- mockSpaceFinder := new(MockSpaceFinder)
- mockRegistryRepository := new(MockRegistryRepository)
- mockWebhooksRepository := new(MockWebhooksRepository)
- mockWebhooksExecutionRepository := new(MockWebhooksExecutionRepository)
- mockAuthorizer := new(MockAuthorizer)
- mockRegistryMetadataHelper := new(MockRegistryMetadataHelper)
- controller := &APIController{
- SpaceFinder: mockSpaceFinder,
- RegistryRepository: mockRegistryRepository,
- WebhooksRepository: mockWebhooksRepository,
- WebhooksExecutionRepository: mockWebhooksExecutionRepository,
- Authorizer: mockAuthorizer,
- RegistryMetadataHelper: mockRegistryMetadataHelper,
- }
-
- regInfo := &RegistryRequestBaseInfo{
- RegistryID: 1,
- RegistryIdentifier: "reg",
- ParentRef: "root/parent",
- }
- space := &gitnesstypes.SpaceCore{ID: 2}
- var permissionChecks []gitnesstypes.PermissionCheck
- mockRegistryMetadataHelper.On("GetRegistryRequestBaseInfo", ctx, "", "reg").Return(regInfo, nil)
- mockSpaceFinder.On("FindByRef", ctx, "root/parent").Return(space, nil)
- mockRegistryMetadataHelper.On(
- "GetPermissionChecks", space, regInfo.RegistryIdentifier, enum.PermissionRegistryView,
- ).Return(permissionChecks)
- mockAuthorizer.On("CheckAll", ctx, mock.Anything, permissionChecks).Return(false, nil)
-
- r := api.GetWebhookExecutionRequestObject{
- RegistryRef: "reg",
- WebhookIdentifier: "webhook",
- WebhookExecutionId: "1",
- }
-
- response, err := controller.GetWebhookExecution(ctx, r)
- assert.NoError(t, err)
- assert.NotNil(t, response)
- assert.IsType(t, api.GetWebhookExecution403JSONResponse{}, response)
- assert.Equal(t, "forbidden", response.(api.GetWebhookExecution403JSONResponse).Message)
-
- mockRegistryMetadataHelper.AssertExpectations(t)
- mockSpaceFinder.AssertExpectations(t)
- mockAuthorizer.AssertExpectations(t)
-}
-
-//nolint:errcheck
-func TestGetWebhookExecution_InvalidExecutionIdentifier(t *testing.T) {
- ctx := context.Background()
- mockSpaceFinder := new(MockSpaceFinder)
- mockRegistryRepository := new(MockRegistryRepository)
- mockWebhooksRepository := new(MockWebhooksRepository)
- mockWebhooksExecutionRepository := new(MockWebhooksExecutionRepository)
- mockAuthorizer := new(MockAuthorizer)
- mockRegistryMetadataHelper := new(MockRegistryMetadataHelper)
- controller := &APIController{
- SpaceFinder: mockSpaceFinder,
- RegistryRepository: mockRegistryRepository,
- WebhooksRepository: mockWebhooksRepository,
- WebhooksExecutionRepository: mockWebhooksExecutionRepository,
- Authorizer: mockAuthorizer,
- RegistryMetadataHelper: mockRegistryMetadataHelper,
- }
-
- regInfo := &RegistryRequestBaseInfo{
- RegistryID: 1,
- RegistryIdentifier: "reg",
- ParentRef: "root/parent",
- }
- space := &gitnesstypes.SpaceCore{ID: 2}
- var permissionChecks []gitnesstypes.PermissionCheck
- mockRegistryMetadataHelper.On("GetRegistryRequestBaseInfo", ctx, "", "reg").Return(regInfo, nil)
- mockSpaceFinder.On("FindByRef", ctx, "root/parent").Return(space, nil)
- mockRegistryMetadataHelper.On(
- "GetPermissionChecks", space, regInfo.RegistryIdentifier, enum.PermissionRegistryView,
- ).Return(permissionChecks)
- mockAuthorizer.On("CheckAll", ctx, mock.Anything, permissionChecks).Return(true, nil)
-
- r := api.GetWebhookExecutionRequestObject{
- RegistryRef: "reg",
- WebhookIdentifier: "webhook",
- WebhookExecutionId: "invalid",
- }
-
- response, err := controller.GetWebhookExecution(ctx, r)
- assert.NoError(t, err)
- assert.NotNil(t, response)
- assert.IsType(t, api.GetWebhookExecution400JSONResponse{}, response)
- assert.Equal(t,
- "invalid webhook execution identifier: invalid, err: strconv.ParseInt: parsing \"invalid\": invalid syntax",
- response.(api.GetWebhookExecution400JSONResponse).Message)
-
- mockRegistryMetadataHelper.AssertExpectations(t)
- mockSpaceFinder.AssertExpectations(t)
- mockAuthorizer.AssertExpectations(t)
-}
-
-//nolint:errcheck
-func TestGetWebhookExecution_FindExecutionError(t *testing.T) {
- ctx := context.Background()
- mockSpaceFinder := new(MockSpaceFinder)
- mockRegistryRepository := new(MockRegistryRepository)
- mockWebhooksRepository := new(MockWebhooksRepository)
- mockWebhooksExecutionRepository := new(MockWebhooksExecutionRepository)
- mockAuthorizer := new(MockAuthorizer)
- mockRegistryMetadataHelper := new(MockRegistryMetadataHelper)
- controller := &APIController{
- SpaceFinder: mockSpaceFinder,
- RegistryRepository: mockRegistryRepository,
- WebhooksRepository: mockWebhooksRepository,
- WebhooksExecutionRepository: mockWebhooksExecutionRepository,
- Authorizer: mockAuthorizer,
- RegistryMetadataHelper: mockRegistryMetadataHelper,
- }
-
- regInfo := &RegistryRequestBaseInfo{
- RegistryID: 1,
- RegistryIdentifier: "reg",
- ParentRef: "root/parent",
- }
- space := &gitnesstypes.SpaceCore{ID: 2}
- var permissionChecks []gitnesstypes.PermissionCheck
- mockRegistryMetadataHelper.On("GetRegistryRequestBaseInfo", ctx, "", "reg").Return(regInfo, nil)
- mockSpaceFinder.On("FindByRef", ctx, "root/parent").Return(space, nil)
- mockRegistryMetadataHelper.On("GetPermissionChecks", space, regInfo.RegistryIdentifier,
- enum.PermissionRegistryView).Return(permissionChecks)
- mockAuthorizer.On("CheckAll", ctx, mock.Anything, permissionChecks).Return(true, nil)
- mockWebhooksExecutionRepository.On("Find", ctx, int64(1)).
- Return(nil, fmt.Errorf("error"))
-
- r := api.GetWebhookExecutionRequestObject{
- RegistryRef: "reg",
- WebhookIdentifier: "webhook",
- WebhookExecutionId: "1",
- }
-
- response, err := controller.GetWebhookExecution(ctx, r)
- assert.NoError(t, err)
- assert.NotNil(t, response)
- assert.IsType(t, api.GetWebhookExecution500JSONResponse{}, response)
- assert.Equal(t, "failed to find webhook execution: error",
- response.(api.GetWebhookExecution500JSONResponse).Message)
-
- mockRegistryMetadataHelper.AssertExpectations(t)
- mockSpaceFinder.AssertExpectations(t)
- mockAuthorizer.AssertExpectations(t)
- mockWebhooksExecutionRepository.AssertExpectations(t)
+ // Setup mocks
+ tt.setupMocks(controller, mockSpaceFinder, mockAuthorizer, mockRegistryMetadataHelper, mockWebhooksRepo, mockWebhooksExecRepo)
+
+ // Call function
+ resp, err := controller.GetWebhookExecution(context.Background(), tt.request)
+
+ // Validate response
+ tt.validate(t, resp, err)
+
+ // Verify mock expectations
+ mockSpaceFinder.AssertExpectations(t)
+ mockAuthorizer.AssertExpectations(t)
+ mockRegistryMetadataHelper.AssertExpectations(t)
+ mockWebhooksRepo.AssertExpectations(t)
+ mockWebhooksExecRepo.AssertExpectations(t)
+ })
+ }
}
diff --git a/registry/app/api/controller/metadata/list_webhook_execution_test.go b/registry/app/api/controller/metadata/list_webhook_execution_test.go
index 20e0395e6..5e8783b77 100644
--- a/registry/app/api/controller/metadata/list_webhook_execution_test.go
+++ b/registry/app/api/controller/metadata/list_webhook_execution_test.go
@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+//nolint:lll,revive // revive:disable:unused-parameter
package metadata
import (
@@ -20,8 +21,10 @@ import (
"testing"
"time"
+ "github.com/harness/gitness/registry/app/api/controller/mocks"
api "github.com/harness/gitness/registry/app/api/openapi/contracts/artifact"
"github.com/harness/gitness/registry/types"
+ "github.com/harness/gitness/registry/utils"
gitnesstypes "github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
@@ -29,498 +32,700 @@ import (
"github.com/stretchr/testify/mock"
)
-//nolint:lll
-func TestListWebhookExecutions_Success(t *testing.T) {
- ctx := context.Background()
- mockSpaceFinder := new(MockSpaceFinder)
- mockRegistryRepository := new(MockRegistryRepository)
- mockWebhooksRepository := new(MockWebhooksRepository)
- mockWebhooksExecutionRepository := new(MockWebhooksExecutionRepository)
- mockAuthorizer := new(MockAuthorizer)
- mockRegistryMetadataHelper := new(MockRegistryMetadataHelper)
- controller := &APIController{
- SpaceFinder: mockSpaceFinder,
- RegistryRepository: mockRegistryRepository,
- WebhooksRepository: mockWebhooksRepository,
- WebhooksExecutionRepository: mockWebhooksExecutionRepository,
- Authorizer: mockAuthorizer,
- RegistryMetadataHelper: mockRegistryMetadataHelper,
- }
-
- regInfo := &RegistryRequestBaseInfo{
- RegistryID: 1,
- RegistryIdentifier: "reg",
- ParentRef: "root/parent",
- }
- space := &gitnesstypes.SpaceCore{ID: 2}
- var permissionChecks []gitnesstypes.PermissionCheck
- mockRegistryMetadataHelper.On("GetRegistryRequestBaseInfo", ctx, "", "reg").Return(regInfo, nil)
- mockSpaceFinder.On("FindByRef", ctx, "root/parent").Return(space, nil)
- mockRegistryMetadataHelper.On("GetPermissionChecks", space, regInfo.RegistryIdentifier, enum.PermissionRegistryView).Return(permissionChecks)
- mockAuthorizer.On("CheckAll", ctx, mock.Anything, permissionChecks).Return(true, nil)
- mockRegistryRepository.On("GetByParentIDAndName", ctx, int64(2), "reg").Return(&types.Registry{ID: 3}, nil)
- mockWebhooksRepository.On("GetByRegistryAndIdentifier", ctx, int64(3), "webhook").Return(&gitnesstypes.WebhookCore{ID: 4}, nil)
- mockWebhooksExecutionRepository.On("ListForWebhook", ctx, int64(4), 10, 1, 10).Return([]*gitnesstypes.WebhookExecutionCore{
+func TestListWebhookExecutions(t *testing.T) {
+ tests := []struct {
+ name string
+ request api.ListWebhookExecutionsRequestObject
+ setupMocks func(*mocks.SpaceFinder, *mocks.RegistryRepository, *mocks.WebhooksRepository,
+ *mocks.WebhooksExecutionRepository, *mocks.Authorizer, *mocks.RegistryMetadataHelper)
+ validate func(*testing.T, api.ListWebhookExecutionsResponseObject, error)
+ verifyMocks func(*testing.T, *mocks.SpaceFinder, *mocks.RegistryRepository, *mocks.WebhooksRepository,
+ *mocks.WebhooksExecutionRepository, *mocks.Authorizer, *mocks.RegistryMetadataHelper)
+ }{
{
- ID: 1,
- Created: time.Now().Unix(),
- Duration: 100,
- Error: "none",
- Request: gitnesstypes.WebhookExecutionRequest{Body: "{}", Headers: "headers", URL: "http://example.com"},
- Response: gitnesstypes.WebhookExecutionResponse{Body: "{}", Headers: "headers", Status: "200 OK", StatusCode: 200},
- RetriggerOf: nil,
- Retriggerable: true,
- WebhookID: 4,
- Result: enum.WebhookExecutionResultSuccess,
- TriggerType: enum.WebhookTriggerArtifactCreated,
+ name: "success_case",
+ request: api.ListWebhookExecutionsRequestObject{
+ RegistryRef: "reg",
+ WebhookIdentifier: "webhook",
+ Params: api.ListWebhookExecutionsParams{
+ Size: utils.PageSizePtr(10),
+ Page: utils.PageNumberPtr(1),
+ },
+ },
+ setupMocks: func(mockSpaceFinder *mocks.SpaceFinder, mockRegistryRepo *mocks.RegistryRepository,
+ mockWebhooksRepo *mocks.WebhooksRepository, mockWebhooksExecRepo *mocks.WebhooksExecutionRepository,
+ mockAuthorizer *mocks.Authorizer, mockMetadataHelper *mocks.RegistryMetadataHelper) {
+ regInfo := &types.RegistryRequestBaseInfo{
+ RegistryID: 1,
+ RegistryIdentifier: "reg",
+ ParentRef: "root/parent",
+ }
+ space := &gitnesstypes.SpaceCore{ID: 2}
+ var permissionChecks []gitnesstypes.PermissionCheck
+ // session := &auth.Session{}
+
+ mockMetadataHelper.On("GetRegistryRequestBaseInfo", mock.Anything, "", "reg").Return(regInfo, nil)
+ mockSpaceFinder.On("FindByRef", mock.Anything, "root/parent").Return(space, nil)
+ mockMetadataHelper.On(
+ "GetPermissionChecks",
+ space,
+ regInfo.RegistryIdentifier,
+ enum.PermissionRegistryView,
+ ).Return(permissionChecks)
+ mockAuthorizer.On("CheckAll", mock.Anything, mock.Anything, mock.Anything).Return(true, nil)
+ mockRegistryRepo.On("GetByParentIDAndName", mock.Anything, int64(2), "reg").Return(&types.Registry{ID: 3}, nil)
+ mockWebhooksRepo.On(
+ "GetByRegistryAndIdentifier",
+ mock.Anything,
+ int64(3),
+ "webhook",
+ ).Return(&gitnesstypes.WebhookCore{ID: 4}, nil)
+ mockWebhooksExecRepo.On(
+ "ListForWebhook",
+ mock.Anything,
+ int64(4),
+ 10, 1, 10,
+ ).Return([]*gitnesstypes.WebhookExecutionCore{
+ {
+ ID: 1,
+ Created: time.Now().Unix(),
+ Duration: 100,
+ Error: "none",
+ Request: gitnesstypes.WebhookExecutionRequest{Body: "{}", Headers: "headers", URL: "http://example.com"},
+ Response: gitnesstypes.WebhookExecutionResponse{
+ Body: "{}",
+ Headers: "headers",
+ Status: "200 OK",
+ StatusCode: 200,
+ },
+ RetriggerOf: nil,
+ Retriggerable: true,
+ WebhookID: 4,
+ Result: enum.WebhookExecutionResultSuccess,
+ TriggerType: enum.WebhookTriggerArtifactCreated,
+ },
+ }, nil)
+ mockWebhooksExecRepo.On("CountForWebhook", mock.Anything, int64(4)).Return(int64(1), nil)
+ },
+ validate: func(t *testing.T, response api.ListWebhookExecutionsResponseObject, err error) {
+ assert.NoError(t, err)
+ assert.NotNil(t, response)
+
+ resp, ok := response.(api.ListWebhookExecutions200JSONResponse)
+ assert.True(t, ok, "expected 200 response")
+ assert.Equal(t, api.StatusSUCCESS, resp.Status)
+ assert.Len(t, resp.Data.Executions, 1)
+
+ exec := resp.Data.Executions[0]
+ assert.Equal(t, int64(1), *exec.Id)
+ assert.Equal(t, "none", *exec.Error)
+ assert.Equal(t, "{}", *exec.Request.Body)
+ assert.Equal(t, "headers", *exec.Request.Headers)
+ assert.Equal(t, "http://example.com", *exec.Request.Url)
+ assert.Equal(t, "{}", *exec.Response.Body)
+ assert.Equal(t, "headers", *exec.Response.Headers)
+ assert.Equal(t, "200 OK", *exec.Response.Status)
+ assert.Equal(t, 200, *exec.Response.StatusCode)
+ assert.Equal(t, api.WebhookExecResultSUCCESS, *exec.Result)
+ assert.Equal(t, api.TriggerARTIFACTCREATION, *exec.TriggerType)
+
+ assert.Equal(t, int64(1), *resp.Data.ItemCount)
+ assert.Equal(t, 1, *resp.Data.PageSize)
+ assert.Equal(t, int64(1), *resp.Data.PageIndex)
+ assert.Equal(t, int64(1), *resp.Data.PageCount)
+ },
+ verifyMocks: func(t *testing.T, mockSpaceFinder *mocks.SpaceFinder, mockRegistryRepo *mocks.RegistryRepository,
+ mockWebhooksRepo *mocks.WebhooksRepository, mockWebhooksExecRepo *mocks.WebhooksExecutionRepository,
+ mockAuthorizer *mocks.Authorizer, mockMetadataHelper *mocks.RegistryMetadataHelper) {
+ mockMetadataHelper.AssertExpectations(t)
+ mockSpaceFinder.AssertExpectations(t)
+ mockAuthorizer.AssertExpectations(t)
+ mockRegistryRepo.AssertExpectations(t)
+ mockWebhooksRepo.AssertExpectations(t)
+ mockWebhooksExecRepo.AssertExpectations(t)
+ },
},
- }, nil)
- mockWebhooksExecutionRepository.On("CountForWebhook", ctx, int64(4)).Return(int64(1), nil)
-
- pageSize := api.PageSize(10)
- pageNumber := api.PageNumber(1)
- r := api.ListWebhookExecutionsRequestObject{
- RegistryRef: "reg",
- WebhookIdentifier: "webhook",
- Params: api.ListWebhookExecutionsParams{
- Size: &pageSize,
- Page: &pageNumber,
- },
- }
-
- response, err := controller.ListWebhookExecutions(ctx, r)
- listWebhookExecutions200JSONResponse, ok := response.(api.ListWebhookExecutions200JSONResponse)
- if !ok {
- t.Fatalf("expected api.ListWebhookExecutions200JSONResponse, got %T", response)
- }
- assert.NoError(t, err)
- assert.NotNil(t, response)
- assert.Equal(t, api.StatusSUCCESS, listWebhookExecutions200JSONResponse.Status)
- assert.Len(t, listWebhookExecutions200JSONResponse.Data.Executions, 1)
- assert.Equal(t, int64(1), *listWebhookExecutions200JSONResponse.Data.Executions[0].Id)
- assert.Equal(t, "none", *listWebhookExecutions200JSONResponse.Data.Executions[0].Error)
- assert.Equal(t, "{}", *listWebhookExecutions200JSONResponse.Data.Executions[0].Request.Body)
- assert.Equal(t, "headers", *listWebhookExecutions200JSONResponse.Data.Executions[0].Request.Headers)
- assert.Equal(t, "http://example.com", *listWebhookExecutions200JSONResponse.Data.Executions[0].Request.Url)
- assert.Equal(t, "{}", *listWebhookExecutions200JSONResponse.Data.Executions[0].Response.Body)
- assert.Equal(t, "headers", *listWebhookExecutions200JSONResponse.Data.Executions[0].Response.Headers)
- assert.Equal(t, "200 OK", *listWebhookExecutions200JSONResponse.Data.Executions[0].Response.Status)
- assert.Equal(t, 200, *listWebhookExecutions200JSONResponse.Data.Executions[0].Response.StatusCode)
- assert.Equal(t, api.WebhookExecResultSUCCESS, *listWebhookExecutions200JSONResponse.Data.Executions[0].Result)
- assert.Equal(t, api.TriggerARTIFACTCREATION, *listWebhookExecutions200JSONResponse.Data.Executions[0].TriggerType)
- assert.Equal(t, int64(1), *listWebhookExecutions200JSONResponse.Data.ItemCount)
- assert.Equal(t, 1, *listWebhookExecutions200JSONResponse.Data.PageSize)
- assert.Equal(t, int64(1), *listWebhookExecutions200JSONResponse.Data.PageIndex)
- assert.Equal(t, int64(1), *listWebhookExecutions200JSONResponse.Data.PageCount)
- assert.Equal(t, api.StatusSUCCESS, listWebhookExecutions200JSONResponse.Status)
-
- mockRegistryMetadataHelper.AssertExpectations(t)
- mockSpaceFinder.AssertExpectations(t)
- mockAuthorizer.AssertExpectations(t)
- mockRegistryRepository.AssertExpectations(t)
- mockWebhooksRepository.AssertExpectations(t)
- mockWebhooksExecutionRepository.AssertExpectations(t)
-}
-
-//nolint:lll
-func TestListWebhookExecutions_GetRegistryRequestBaseInfoError(t *testing.T) {
- ctx := context.Background()
- mockRegistryMetadataHelper := new(MockRegistryMetadataHelper)
- controller := &APIController{
- RegistryMetadataHelper: mockRegistryMetadataHelper,
- }
-
- mockRegistryMetadataHelper.On("GetRegistryRequestBaseInfo", ctx, "", "reg").Return(nil, fmt.Errorf("error"))
-
- pageSize := api.PageSize(10)
- pageNumber := api.PageNumber(11)
- r := api.ListWebhookExecutionsRequestObject{
- RegistryRef: "reg",
- WebhookIdentifier: "webhook",
- Params: api.ListWebhookExecutionsParams{
- Size: &pageSize,
- Page: &pageNumber,
- },
- }
-
- response, err := controller.ListWebhookExecutions(ctx, r)
- assert.NoError(t, err)
- assert.NotNil(t, response)
- assert.IsType(t, api.ListWebhookExecutions500JSONResponse{}, response)
- assert.Equal(t, "error", response.(api.ListWebhookExecutions500JSONResponse).Message) //nolint:errcheck
- mockRegistryMetadataHelper.AssertExpectations(t)
-}
-
-//nolint:lll
-func TestListWebhookExecutions_FindByRefError(t *testing.T) {
- ctx := context.Background()
- mockSpaceFinder := new(MockSpaceFinder)
- mockRegistryMetadataHelper := new(MockRegistryMetadataHelper)
- controller := &APIController{
- SpaceFinder: mockSpaceFinder,
- RegistryMetadataHelper: mockRegistryMetadataHelper,
- }
-
- regInfo := &RegistryRequestBaseInfo{
- RegistryID: 1,
- RegistryIdentifier: "reg",
- ParentRef: "root/parent",
- }
-
- mockRegistryMetadataHelper.On("GetRegistryRequestBaseInfo", ctx, "", "reg").Return(regInfo, nil)
- mockSpaceFinder.On("FindByRef", ctx, "root/parent").Return(nil, fmt.Errorf("error"))
-
- pageSize := api.PageSize(10)
- pageNumber := api.PageNumber(11)
- r := api.ListWebhookExecutionsRequestObject{
- RegistryRef: "reg",
- WebhookIdentifier: "webhook",
- Params: api.ListWebhookExecutionsParams{
- Size: &pageSize,
- Page: &pageNumber,
- },
- }
-
- response, err := controller.ListWebhookExecutions(ctx, r)
- assert.NoError(t, err)
- assert.NotNil(t, response)
- assert.IsType(t, api.ListWebhookExecutions500JSONResponse{}, response)
- assert.Equal(t, "error", response.(api.ListWebhookExecutions500JSONResponse).Message) //nolint:errcheck
-
- mockRegistryMetadataHelper.AssertExpectations(t)
- mockSpaceFinder.AssertExpectations(t)
-}
-
-//nolint:lll
-func TestListWebhookExecutions_CheckPermissionsFails(t *testing.T) {
- ctx := context.Background()
- mockSpaceFinder := new(MockSpaceFinder)
- mockAuthorizer := new(MockAuthorizer)
- mockRegistryMetadataHelper := new(MockRegistryMetadataHelper)
- controller := &APIController{
- SpaceFinder: mockSpaceFinder,
- Authorizer: mockAuthorizer,
- RegistryMetadataHelper: mockRegistryMetadataHelper,
- }
-
- regInfo := &RegistryRequestBaseInfo{
- RegistryID: 1,
- RegistryIdentifier: "reg",
- ParentRef: "root/parent",
- }
- space := &gitnesstypes.SpaceCore{ID: 2}
- var permissionChecks []gitnesstypes.PermissionCheck
-
- mockRegistryMetadataHelper.On("GetRegistryRequestBaseInfo", ctx, "", "reg").Return(regInfo, nil)
- mockSpaceFinder.On("FindByRef", ctx, "root/parent").Return(space, nil)
- mockRegistryMetadataHelper.On("GetPermissionChecks", space, regInfo.RegistryIdentifier, enum.PermissionRegistryView).Return(permissionChecks)
- mockAuthorizer.On("CheckAll", ctx, mock.Anything, permissionChecks).Return(false, nil)
-
- pageSize := api.PageSize(10)
- pageNumber := api.PageNumber(11)
- r := api.ListWebhookExecutionsRequestObject{
- RegistryRef: "reg",
- WebhookIdentifier: "webhook",
- Params: api.ListWebhookExecutionsParams{
- Size: &pageSize,
- Page: &pageNumber,
- },
- }
-
- response, err := controller.ListWebhookExecutions(ctx, r)
- assert.NoError(t, err)
- assert.NotNil(t, response)
- assert.IsType(t, api.ListWebhookExecutions403JSONResponse{}, response)
- assert.Equal(t, "forbidden", response.(api.ListWebhookExecutions403JSONResponse).Message) //nolint:errcheck
-
- mockRegistryMetadataHelper.AssertExpectations(t)
- mockSpaceFinder.AssertExpectations(t)
- mockAuthorizer.AssertExpectations(t)
-}
-
-//nolint:lll
-func TestListWebhookExecutions_FailedToDetRegistry(t *testing.T) {
- ctx := context.Background()
- mockSpaceFinder := new(MockSpaceFinder)
- mockRegistryRepository := new(MockRegistryRepository)
- mockWebhooksRepository := new(MockWebhooksRepository)
- mockWebhooksExecutionRepository := new(MockWebhooksExecutionRepository)
- mockAuthorizer := new(MockAuthorizer)
- mockRegistryMetadataHelper := new(MockRegistryMetadataHelper)
- controller := &APIController{
- SpaceFinder: mockSpaceFinder,
- RegistryRepository: mockRegistryRepository,
- WebhooksRepository: mockWebhooksRepository,
- WebhooksExecutionRepository: mockWebhooksExecutionRepository,
- Authorizer: mockAuthorizer,
- RegistryMetadataHelper: mockRegistryMetadataHelper,
- }
-
- regInfo := &RegistryRequestBaseInfo{
- RegistryID: 1,
- RegistryIdentifier: "reg",
- ParentRef: "root/parent",
- }
- space := &gitnesstypes.SpaceCore{ID: 2}
- var permissionChecks []gitnesstypes.PermissionCheck
- mockRegistryMetadataHelper.On("GetRegistryRequestBaseInfo", ctx, "", "reg").Return(regInfo, nil)
- mockSpaceFinder.On("FindByRef", ctx, "root/parent").Return(space, nil)
- mockRegistryMetadataHelper.On("GetPermissionChecks", space, regInfo.RegistryIdentifier, enum.PermissionRegistryView).Return(permissionChecks)
- mockAuthorizer.On("CheckAll", ctx, mock.Anything, permissionChecks).Return(true, nil)
- mockRegistryRepository.On("GetByParentIDAndName", ctx, int64(2), "reg").Return(nil, fmt.Errorf("error"))
-
- pageSize := api.PageSize(10)
- pageNumber := api.PageNumber(1)
- r := api.ListWebhookExecutionsRequestObject{
- RegistryRef: "reg",
- WebhookIdentifier: "webhook",
- Params: api.ListWebhookExecutionsParams{
- Size: &pageSize,
- Page: &pageNumber,
- },
- }
-
- response, err := controller.ListWebhookExecutions(ctx, r)
- assert.NoError(t, err)
- assert.NotNil(t, response)
- assert.IsType(t, api.ListWebhookExecutions500JSONResponse{}, response)
- assert.Equal(t, "failed to find registry: error", response.(api.ListWebhookExecutions500JSONResponse).Message) //nolint:errcheck
-
- mockRegistryMetadataHelper.AssertExpectations(t)
- mockSpaceFinder.AssertExpectations(t)
- mockAuthorizer.AssertExpectations(t)
- mockRegistryRepository.AssertExpectations(t)
-}
-
-//nolint:lll
-func TestListWebhookExecutions_FailedToGetWebhook(t *testing.T) {
- ctx := context.Background()
- mockSpaceFinder := new(MockSpaceFinder)
- mockRegistryRepository := new(MockRegistryRepository)
- mockWebhooksRepository := new(MockWebhooksRepository)
- mockWebhooksExecutionRepository := new(MockWebhooksExecutionRepository)
- mockAuthorizer := new(MockAuthorizer)
- mockRegistryMetadataHelper := new(MockRegistryMetadataHelper)
- controller := &APIController{
- SpaceFinder: mockSpaceFinder,
- RegistryRepository: mockRegistryRepository,
- WebhooksRepository: mockWebhooksRepository,
- WebhooksExecutionRepository: mockWebhooksExecutionRepository,
- Authorizer: mockAuthorizer,
- RegistryMetadataHelper: mockRegistryMetadataHelper,
- }
-
- regInfo := &RegistryRequestBaseInfo{
- RegistryID: 1,
- RegistryIdentifier: "reg",
- ParentRef: "root/parent",
- }
- space := &gitnesstypes.SpaceCore{ID: 2}
- var permissionChecks []gitnesstypes.PermissionCheck
- mockRegistryMetadataHelper.On("GetRegistryRequestBaseInfo", ctx, "", "reg").Return(regInfo, nil)
- mockSpaceFinder.On("FindByRef", ctx, "root/parent").Return(space, nil)
- mockRegistryMetadataHelper.On("GetPermissionChecks", space, regInfo.RegistryIdentifier, enum.PermissionRegistryView).Return(permissionChecks)
- mockAuthorizer.On("CheckAll", ctx, mock.Anything, permissionChecks).Return(true, nil)
- mockRegistryRepository.On("GetByParentIDAndName", ctx, int64(2), "reg").Return(&types.Registry{ID: 3}, nil)
- mockWebhooksRepository.On("GetByRegistryAndIdentifier", ctx, int64(3), "webhook").Return(nil, fmt.Errorf("error"))
-
- pageSize := api.PageSize(10)
- pageNumber := api.PageNumber(1)
- r := api.ListWebhookExecutionsRequestObject{
- RegistryRef: "reg",
- WebhookIdentifier: "webhook",
- Params: api.ListWebhookExecutionsParams{
- Size: &pageSize,
- Page: &pageNumber,
- },
- }
-
- response, err := controller.ListWebhookExecutions(ctx, r)
- assert.NoError(t, err)
- assert.NotNil(t, response)
- assert.IsType(t, api.ListWebhookExecutions500JSONResponse{}, response)
- assert.Equal(t, "failed to find webhook [webhook] : error", response.(api.ListWebhookExecutions500JSONResponse).Message) //nolint:errcheck
-
- mockRegistryMetadataHelper.AssertExpectations(t)
- mockSpaceFinder.AssertExpectations(t)
- mockAuthorizer.AssertExpectations(t)
- mockRegistryRepository.AssertExpectations(t)
- mockWebhooksRepository.AssertExpectations(t)
-}
-
-//nolint:lll
-func TestListWebhookExecutions_FailedToGetWebhookExecutions(t *testing.T) {
- ctx := context.Background()
- mockSpaceFinder := new(MockSpaceFinder)
- mockRegistryRepository := new(MockRegistryRepository)
- mockWebhooksRepository := new(MockWebhooksRepository)
- mockWebhooksExecutionRepository := new(MockWebhooksExecutionRepository)
- mockAuthorizer := new(MockAuthorizer)
- mockRegistryMetadataHelper := new(MockRegistryMetadataHelper)
- controller := &APIController{
- SpaceFinder: mockSpaceFinder,
- RegistryRepository: mockRegistryRepository,
- WebhooksRepository: mockWebhooksRepository,
- WebhooksExecutionRepository: mockWebhooksExecutionRepository,
- Authorizer: mockAuthorizer,
- RegistryMetadataHelper: mockRegistryMetadataHelper,
- }
-
- regInfo := &RegistryRequestBaseInfo{
- RegistryID: 1,
- RegistryIdentifier: "reg",
- ParentRef: "root/parent",
- }
- space := &gitnesstypes.SpaceCore{ID: 2}
- var permissionChecks []gitnesstypes.PermissionCheck
- mockRegistryMetadataHelper.On("GetRegistryRequestBaseInfo", ctx, "", "reg").Return(regInfo, nil)
- mockSpaceFinder.On("FindByRef", ctx, "root/parent").Return(space, nil)
- mockRegistryMetadataHelper.On("GetPermissionChecks", space, regInfo.RegistryIdentifier, enum.PermissionRegistryView).Return(permissionChecks)
- mockAuthorizer.On("CheckAll", ctx, mock.Anything, permissionChecks).Return(true, nil)
- mockRegistryRepository.On("GetByParentIDAndName", ctx, int64(2), "reg").Return(&types.Registry{ID: 3}, nil)
- mockWebhooksRepository.On("GetByRegistryAndIdentifier", ctx, int64(3), "webhook").Return(&gitnesstypes.WebhookCore{ID: 4}, nil)
- mockWebhooksExecutionRepository.On("ListForWebhook", ctx, int64(4), 10, 1, 10).Return(nil, fmt.Errorf("error"))
-
- pageSize := api.PageSize(10)
- pageNumber := api.PageNumber(1)
- r := api.ListWebhookExecutionsRequestObject{
- RegistryRef: "reg",
- WebhookIdentifier: "webhook",
- Params: api.ListWebhookExecutionsParams{
- Size: &pageSize,
- Page: &pageNumber,
- },
- }
-
- response, err := controller.ListWebhookExecutions(ctx, r)
- assert.NoError(t, err)
- assert.NotNil(t, response)
- assert.IsType(t, api.ListWebhookExecutions500JSONResponse{}, response)
- assert.Equal(t, "failed to list webhook executions: error", response.(api.ListWebhookExecutions500JSONResponse).Message) //nolint:errcheck
-
- mockRegistryMetadataHelper.AssertExpectations(t)
- mockSpaceFinder.AssertExpectations(t)
- mockAuthorizer.AssertExpectations(t)
- mockRegistryRepository.AssertExpectations(t)
- mockWebhooksRepository.AssertExpectations(t)
- mockWebhooksExecutionRepository.AssertExpectations(t)
-}
-
-//nolint:lll
-func TestListWebhookExecutions_FailedToGetWebhooksCount(t *testing.T) {
- ctx := context.Background()
- mockSpaceFinder := new(MockSpaceFinder)
- mockRegistryRepository := new(MockRegistryRepository)
- mockWebhooksRepository := new(MockWebhooksRepository)
- mockWebhooksExecutionRepository := new(MockWebhooksExecutionRepository)
- mockAuthorizer := new(MockAuthorizer)
- mockRegistryMetadataHelper := new(MockRegistryMetadataHelper)
- controller := &APIController{
- SpaceFinder: mockSpaceFinder,
- RegistryRepository: mockRegistryRepository,
- WebhooksRepository: mockWebhooksRepository,
- WebhooksExecutionRepository: mockWebhooksExecutionRepository,
- Authorizer: mockAuthorizer,
- RegistryMetadataHelper: mockRegistryMetadataHelper,
- }
-
- regInfo := &RegistryRequestBaseInfo{
- RegistryID: 1,
- RegistryIdentifier: "reg",
- ParentRef: "root/parent",
- }
- space := &gitnesstypes.SpaceCore{ID: 2}
- var permissionChecks []gitnesstypes.PermissionCheck
- mockRegistryMetadataHelper.On("GetRegistryRequestBaseInfo", ctx, "", "reg").Return(regInfo, nil)
- mockSpaceFinder.On("FindByRef", ctx, "root/parent").Return(space, nil)
- mockRegistryMetadataHelper.On("GetPermissionChecks", space, regInfo.RegistryIdentifier, enum.PermissionRegistryView).Return(permissionChecks)
- mockAuthorizer.On("CheckAll", ctx, mock.Anything, permissionChecks).Return(true, nil)
- mockRegistryRepository.On("GetByParentIDAndName", ctx, int64(2), "reg").Return(&types.Registry{ID: 3}, nil)
- mockWebhooksRepository.On("GetByRegistryAndIdentifier", ctx, int64(3), "webhook").Return(&gitnesstypes.WebhookCore{ID: 4}, nil)
- mockWebhooksExecutionRepository.On("ListForWebhook", ctx, int64(4), 10, 1, 10).Return([]*gitnesstypes.WebhookExecutionCore{
{
- ID: 1,
- Created: time.Now().Unix(),
- Duration: 100,
- Error: "none",
- Request: gitnesstypes.WebhookExecutionRequest{Body: "{}", Headers: "headers", URL: "http://example.com"},
- Response: gitnesstypes.WebhookExecutionResponse{Body: "{}", Headers: "headers", Status: "200 OK", StatusCode: 200},
- RetriggerOf: nil,
- Retriggerable: true,
- WebhookID: 4,
- Result: enum.WebhookExecutionResultSuccess,
- TriggerType: enum.WebhookTriggerArtifactCreated,
+ name: "get_registry_request_base_info_error",
+ request: api.ListWebhookExecutionsRequestObject{
+ RegistryRef: "reg",
+ WebhookIdentifier: "webhook",
+ Params: api.ListWebhookExecutionsParams{
+ Size: utils.PageSizePtr(10),
+ Page: utils.PageNumberPtr(11),
+ },
+ },
+ setupMocks: func(_ *mocks.SpaceFinder, _ *mocks.RegistryRepository,
+ _ *mocks.WebhooksRepository, _ *mocks.WebhooksExecutionRepository,
+ _ *mocks.Authorizer, mockMetadataHelper *mocks.RegistryMetadataHelper) {
+ mockMetadataHelper.On("GetRegistryRequestBaseInfo", mock.Anything, "", "reg").Return(nil, fmt.Errorf("error"))
+ },
+ validate: func(t *testing.T, response api.ListWebhookExecutionsResponseObject, err error) {
+ assert.NoError(t, err)
+ assert.NotNil(t, response)
+ resp, ok := response.(api.ListWebhookExecutions500JSONResponse)
+ assert.True(t, ok, "expected 500 response")
+ assert.Equal(t, "error", resp.Message)
+ },
+ verifyMocks: func(t *testing.T, _ *mocks.SpaceFinder, _ *mocks.RegistryRepository,
+ _ *mocks.WebhooksRepository, _ *mocks.WebhooksExecutionRepository,
+ _ *mocks.Authorizer, mockMetadataHelper *mocks.RegistryMetadataHelper) {
+ mockMetadataHelper.AssertExpectations(t)
+ // Other mocks should not have any expectations
+ },
},
- }, nil)
- mockWebhooksExecutionRepository.On("CountForWebhook", ctx, int64(4)).Return(nil, fmt.Errorf("error"))
+ {
+ name: "find_by_ref_error",
+ request: api.ListWebhookExecutionsRequestObject{
+ RegistryRef: "reg",
+ WebhookIdentifier: "webhook",
+ Params: api.ListWebhookExecutionsParams{
+ Size: utils.PageSizePtr(10),
+ Page: utils.PageNumberPtr(11),
+ },
+ },
+ setupMocks: func(mockSpaceFinder *mocks.SpaceFinder, _ *mocks.RegistryRepository,
+ _ *mocks.WebhooksRepository, _ *mocks.WebhooksExecutionRepository,
+ _ *mocks.Authorizer, mockMetadataHelper *mocks.RegistryMetadataHelper) {
+ regInfo := &types.RegistryRequestBaseInfo{
+ RegistryID: 1,
+ RegistryIdentifier: "reg",
+ ParentRef: "root/parent",
+ }
+ mockMetadataHelper.On("GetRegistryRequestBaseInfo", mock.Anything, "", "reg").Return(regInfo, nil)
+ mockSpaceFinder.On("FindByRef", mock.Anything, "root/parent").Return(nil, fmt.Errorf("error"))
+ },
+ validate: func(t *testing.T, response api.ListWebhookExecutionsResponseObject, err error) {
+ assert.NoError(t, err)
+ assert.NotNil(t, response)
+ resp, ok := response.(api.ListWebhookExecutions500JSONResponse)
+ assert.True(t, ok, "expected 500 response")
+ assert.Equal(t, "error", resp.Message)
+ },
+ verifyMocks: func(t *testing.T, mockSpaceFinder *mocks.SpaceFinder, mockRegistryRepo *mocks.RegistryRepository,
+ mockWebhooksRepo *mocks.WebhooksRepository, mockWebhooksExecRepo *mocks.WebhooksExecutionRepository,
+ mockAuthorizer *mocks.Authorizer, mockMetadataHelper *mocks.RegistryMetadataHelper) {
+ mockMetadataHelper.AssertExpectations(t)
+ mockSpaceFinder.AssertExpectations(t)
+ // Other mocks should not have any expectations
+ mockAuthorizer.AssertNotCalled(t, mock.Anything)
+ mockRegistryRepo.AssertNotCalled(t, mock.Anything)
+ mockWebhooksRepo.AssertNotCalled(t, mock.Anything)
+ mockWebhooksExecRepo.AssertNotCalled(t, mock.Anything)
+ },
+ },
+ {
+ name: "check_permissions_fails",
+ request: api.ListWebhookExecutionsRequestObject{
+ RegistryRef: "reg",
+ WebhookIdentifier: "webhook",
+ Params: api.ListWebhookExecutionsParams{
+ Size: utils.PageSizePtr(10),
+ Page: utils.PageNumberPtr(11),
+ },
+ },
+ setupMocks: func(mockSpaceFinder *mocks.SpaceFinder, mockRegistryRepo *mocks.RegistryRepository,
+ mockWebhooksRepo *mocks.WebhooksRepository, mockWebhooksExecRepo *mocks.WebhooksExecutionRepository,
+ mockAuthorizer *mocks.Authorizer, mockMetadataHelper *mocks.RegistryMetadataHelper) {
+ regInfo := &types.RegistryRequestBaseInfo{
+ RegistryID: 1,
+ RegistryIdentifier: "reg",
+ ParentRef: "root/parent",
+ }
+ space := &gitnesstypes.SpaceCore{ID: 2}
+ var permissionChecks []gitnesstypes.PermissionCheck
- pageSize := api.PageSize(10)
- pageNumber := api.PageNumber(1)
- r := api.ListWebhookExecutionsRequestObject{
- RegistryRef: "reg",
- WebhookIdentifier: "webhook",
- Params: api.ListWebhookExecutionsParams{
- Size: &pageSize,
- Page: &pageNumber,
+ mockMetadataHelper.On("GetRegistryRequestBaseInfo", mock.Anything, "", "reg").Return(regInfo, nil)
+ mockSpaceFinder.On("FindByRef", mock.Anything, "root/parent").Return(space, nil)
+ mockMetadataHelper.On(
+ "GetPermissionChecks",
+ space,
+ regInfo.RegistryIdentifier,
+ enum.PermissionRegistryView,
+ ).Return(permissionChecks)
+ mockAuthorizer.On("CheckAll", mock.Anything, mock.Anything, mock.Anything).Return(false, nil)
+ },
+ validate: func(t *testing.T, response api.ListWebhookExecutionsResponseObject, err error) {
+ assert.NoError(t, err)
+ assert.NotNil(t, response)
+ resp, ok := response.(api.ListWebhookExecutions403JSONResponse)
+ assert.True(t, ok, "expected 403 response")
+ assert.Equal(t, "forbidden", resp.Message)
+ },
+ verifyMocks: func(t *testing.T, mockSpaceFinder *mocks.SpaceFinder, mockRegistryRepo *mocks.RegistryRepository,
+ mockWebhooksRepo *mocks.WebhooksRepository, mockWebhooksExecRepo *mocks.WebhooksExecutionRepository,
+ mockAuthorizer *mocks.Authorizer, mockMetadataHelper *mocks.RegistryMetadataHelper) {
+ mockMetadataHelper.AssertExpectations(t)
+ mockSpaceFinder.AssertExpectations(t)
+ mockAuthorizer.AssertExpectations(t)
+ // Other mocks should not have any expectations
+ mockRegistryRepo.AssertNotCalled(t, mock.Anything)
+ mockWebhooksRepo.AssertNotCalled(t, mock.Anything)
+ mockWebhooksExecRepo.AssertNotCalled(t, mock.Anything)
+ },
+ },
+ {
+ name: "failed_to_get_registry",
+ request: api.ListWebhookExecutionsRequestObject{
+ RegistryRef: "reg",
+ WebhookIdentifier: "webhook",
+ Params: api.ListWebhookExecutionsParams{
+ Size: utils.PageSizePtr(10),
+ Page: utils.PageNumberPtr(1),
+ },
+ },
+ setupMocks: func(mockSpaceFinder *mocks.SpaceFinder, mockRegistryRepo *mocks.RegistryRepository,
+ mockWebhooksRepo *mocks.WebhooksRepository, mockWebhooksExecRepo *mocks.WebhooksExecutionRepository,
+ mockAuthorizer *mocks.Authorizer, mockMetadataHelper *mocks.RegistryMetadataHelper) {
+ regInfo := &types.RegistryRequestBaseInfo{
+ RegistryID: 1,
+ RegistryIdentifier: "reg",
+ ParentRef: "root/parent",
+ }
+ space := &gitnesstypes.SpaceCore{ID: 2}
+ var permissionChecks []gitnesstypes.PermissionCheck
+
+ mockMetadataHelper.On("GetRegistryRequestBaseInfo", mock.Anything, "", "reg").Return(regInfo, nil)
+ mockSpaceFinder.On("FindByRef", mock.Anything, "root/parent").Return(space, nil)
+ mockMetadataHelper.On(
+ "GetPermissionChecks",
+ space,
+ regInfo.RegistryIdentifier,
+ enum.PermissionRegistryView,
+ ).Return(permissionChecks)
+ mockAuthorizer.On("CheckAll", mock.Anything, mock.Anything, mock.Anything).Return(true, nil)
+ mockRegistryRepo.On("GetByParentIDAndName", mock.Anything, int64(2), "reg").Return(nil, fmt.Errorf("error"))
+ },
+ validate: func(t *testing.T, response api.ListWebhookExecutionsResponseObject, err error) {
+ assert.NoError(t, err)
+ assert.NotNil(t, response)
+ resp, ok := response.(api.ListWebhookExecutions500JSONResponse)
+ assert.True(t, ok, "expected 500 response")
+ assert.Equal(t, "failed to find registry: error", resp.Message)
+ },
+ verifyMocks: func(t *testing.T, mockSpaceFinder *mocks.SpaceFinder, mockRegistryRepo *mocks.RegistryRepository,
+ mockWebhooksRepo *mocks.WebhooksRepository, mockWebhooksExecRepo *mocks.WebhooksExecutionRepository,
+ mockAuthorizer *mocks.Authorizer, mockMetadataHelper *mocks.RegistryMetadataHelper) {
+ mockMetadataHelper.AssertExpectations(t)
+ mockSpaceFinder.AssertExpectations(t)
+ mockAuthorizer.AssertExpectations(t)
+ mockRegistryRepo.AssertExpectations(t)
+ // Other mocks should not have any expectations
+ mockWebhooksRepo.AssertNotCalled(t, mock.Anything)
+ mockWebhooksExecRepo.AssertNotCalled(t, mock.Anything)
+ },
+ },
+ {
+ name: "failed_to_get_webhook",
+ request: api.ListWebhookExecutionsRequestObject{
+ RegistryRef: "reg",
+ WebhookIdentifier: "webhook",
+ Params: api.ListWebhookExecutionsParams{
+ Size: utils.PageSizePtr(10),
+ Page: utils.PageNumberPtr(1),
+ },
+ },
+ setupMocks: func(mockSpaceFinder *mocks.SpaceFinder, mockRegistryRepo *mocks.RegistryRepository,
+ mockWebhooksRepo *mocks.WebhooksRepository, mockWebhooksExecRepo *mocks.WebhooksExecutionRepository,
+ mockAuthorizer *mocks.Authorizer, mockMetadataHelper *mocks.RegistryMetadataHelper) {
+ regInfo := &types.RegistryRequestBaseInfo{
+ RegistryID: 1,
+ RegistryIdentifier: "reg",
+ ParentRef: "root/parent",
+ }
+ space := &gitnesstypes.SpaceCore{ID: 2}
+ var permissionChecks []gitnesstypes.PermissionCheck
+
+ mockMetadataHelper.On("GetRegistryRequestBaseInfo", mock.Anything, "", "reg").Return(regInfo, nil)
+ mockSpaceFinder.On("FindByRef", mock.Anything, "root/parent").Return(space, nil)
+ mockMetadataHelper.On(
+ "GetPermissionChecks",
+ space,
+ regInfo.RegistryIdentifier,
+ enum.PermissionRegistryView,
+ ).Return(permissionChecks)
+ mockAuthorizer.On("CheckAll", mock.Anything, mock.Anything, mock.Anything).Return(true, nil)
+ mockRegistryRepo.On("GetByParentIDAndName", mock.Anything, int64(2), "reg").Return(&types.Registry{ID: 3}, nil)
+ mockWebhooksRepo.On("GetByRegistryAndIdentifier", mock.Anything, int64(3), "webhook").Return(nil, fmt.Errorf("error"))
+ },
+ validate: func(t *testing.T, response api.ListWebhookExecutionsResponseObject, err error) {
+ assert.NoError(t, err)
+ assert.NotNil(t, response)
+ resp, ok := response.(api.ListWebhookExecutions500JSONResponse)
+ assert.True(t, ok, "expected 500 response")
+ assert.Equal(t, "failed to find webhook [webhook] : error", resp.Message)
+ },
+ verifyMocks: func(t *testing.T, mockSpaceFinder *mocks.SpaceFinder, mockRegistryRepo *mocks.RegistryRepository,
+ mockWebhooksRepo *mocks.WebhooksRepository, mockWebhooksExecRepo *mocks.WebhooksExecutionRepository,
+ mockAuthorizer *mocks.Authorizer, mockMetadataHelper *mocks.RegistryMetadataHelper) {
+ mockMetadataHelper.AssertExpectations(t)
+ mockSpaceFinder.AssertExpectations(t)
+ mockAuthorizer.AssertExpectations(t)
+ mockRegistryRepo.AssertExpectations(t)
+ mockWebhooksRepo.AssertExpectations(t)
+ // Other mocks should not have any expectations
+ mockWebhooksExecRepo.AssertNotCalled(t, mock.Anything)
+ },
+ },
+ {
+ name: "failed_to_list_webhook_executions",
+ request: api.ListWebhookExecutionsRequestObject{
+ RegistryRef: "reg",
+ WebhookIdentifier: "webhook",
+ Params: api.ListWebhookExecutionsParams{
+ Size: utils.PageSizePtr(10),
+ Page: utils.PageNumberPtr(1),
+ },
+ },
+ setupMocks: func(mockSpaceFinder *mocks.SpaceFinder, mockRegistryRepo *mocks.RegistryRepository,
+ mockWebhooksRepo *mocks.WebhooksRepository, mockWebhooksExecRepo *mocks.WebhooksExecutionRepository,
+ mockAuthorizer *mocks.Authorizer, mockMetadataHelper *mocks.RegistryMetadataHelper) {
+ regInfo := &types.RegistryRequestBaseInfo{
+ RegistryID: 1,
+ RegistryIdentifier: "reg",
+ ParentRef: "root/parent",
+ }
+ space := &gitnesstypes.SpaceCore{ID: 2}
+ var permissionChecks []gitnesstypes.PermissionCheck
+
+ mockMetadataHelper.On("GetRegistryRequestBaseInfo", mock.Anything, "", "reg").Return(regInfo, nil)
+ mockSpaceFinder.On("FindByRef", mock.Anything, "root/parent").Return(space, nil)
+ mockMetadataHelper.On(
+ "GetPermissionChecks",
+ space,
+ regInfo.RegistryIdentifier,
+ enum.PermissionRegistryView,
+ ).Return(permissionChecks)
+ mockAuthorizer.On("CheckAll", mock.Anything, mock.Anything, mock.Anything).Return(true, nil)
+ mockRegistryRepo.On("GetByParentIDAndName", mock.Anything, int64(2), "reg").Return(&types.Registry{ID: 3}, nil)
+ mockWebhooksRepo.On(
+ "GetByRegistryAndIdentifier",
+ mock.Anything,
+ int64(3),
+ "webhook",
+ ).Return(&gitnesstypes.WebhookCore{ID: 4}, nil)
+ mockWebhooksExecRepo.On("ListForWebhook", mock.Anything, int64(4), 10, 1, 10).Return(nil, fmt.Errorf("error"))
+ },
+ validate: func(t *testing.T, response api.ListWebhookExecutionsResponseObject, err error) {
+ assert.NoError(t, err)
+ assert.NotNil(t, response)
+ resp, ok := response.(api.ListWebhookExecutions500JSONResponse)
+ assert.True(t, ok, "expected 500 response")
+ assert.Equal(t, "failed to list webhook executions: error", resp.Message)
+ },
+ verifyMocks: func(t *testing.T, mockSpaceFinder *mocks.SpaceFinder, mockRegistryRepo *mocks.RegistryRepository,
+ mockWebhooksRepo *mocks.WebhooksRepository, mockWebhooksExecRepo *mocks.WebhooksExecutionRepository,
+ mockAuthorizer *mocks.Authorizer, mockMetadataHelper *mocks.RegistryMetadataHelper) {
+ mockMetadataHelper.AssertExpectations(t)
+ mockSpaceFinder.AssertExpectations(t)
+ mockAuthorizer.AssertExpectations(t)
+ mockRegistryRepo.AssertExpectations(t)
+ mockWebhooksRepo.AssertExpectations(t)
+ mockWebhooksExecRepo.AssertExpectations(t)
+ },
+ },
+ {
+ name: "failed_to_get_webhook_executions_count",
+ request: api.ListWebhookExecutionsRequestObject{
+ RegistryRef: "reg",
+ WebhookIdentifier: "webhook",
+ Params: api.ListWebhookExecutionsParams{
+ Size: utils.PageSizePtr(10),
+ Page: utils.PageNumberPtr(1),
+ },
+ },
+ setupMocks: func(mockSpaceFinder *mocks.SpaceFinder, mockRegistryRepo *mocks.RegistryRepository,
+ mockWebhooksRepo *mocks.WebhooksRepository, mockWebhooksExecRepo *mocks.WebhooksExecutionRepository,
+ mockAuthorizer *mocks.Authorizer, mockMetadataHelper *mocks.RegistryMetadataHelper) {
+ regInfo := &types.RegistryRequestBaseInfo{
+ RegistryID: 1,
+ RegistryIdentifier: "reg",
+ ParentRef: "root/parent",
+ }
+ space := &gitnesstypes.SpaceCore{ID: 2}
+ var permissionChecks []gitnesstypes.PermissionCheck
+
+ mockMetadataHelper.On("GetRegistryRequestBaseInfo", mock.Anything, "", "reg").Return(regInfo, nil)
+ mockSpaceFinder.On("FindByRef", mock.Anything, "root/parent").Return(space, nil)
+ mockMetadataHelper.On(
+ "GetPermissionChecks",
+ space,
+ regInfo.RegistryIdentifier,
+ enum.PermissionRegistryView,
+ ).Return(permissionChecks)
+ mockAuthorizer.On("CheckAll", mock.Anything, mock.Anything, mock.Anything).Return(true, nil)
+ mockRegistryRepo.On("GetByParentIDAndName", mock.Anything, int64(2), "reg").Return(&types.Registry{ID: 3}, nil)
+ mockWebhooksRepo.On(
+ "GetByRegistryAndIdentifier",
+ mock.Anything,
+ int64(3),
+ "webhook",
+ ).Return(&gitnesstypes.WebhookCore{ID: 4}, nil)
+ mockWebhooksExecRepo.On(
+ "ListForWebhook",
+ mock.Anything,
+ int64(4),
+ 10, 1, 10,
+ ).Return([]*gitnesstypes.WebhookExecutionCore{
+ {
+ ID: 1,
+ Created: time.Now().Unix(),
+ Duration: 100,
+ Error: "none",
+ Request: gitnesstypes.WebhookExecutionRequest{Body: "{}", Headers: "headers", URL: "http://example.com"},
+ Response: gitnesstypes.WebhookExecutionResponse{
+ Body: "{}",
+ Headers: "headers",
+ Status: "200 OK",
+ StatusCode: 200,
+ },
+ RetriggerOf: nil,
+ Retriggerable: true,
+ WebhookID: 4,
+ Result: enum.WebhookExecutionResultSuccess,
+ TriggerType: enum.WebhookTriggerArtifactCreated,
+ },
+ }, nil)
+ mockWebhooksExecRepo.On("CountForWebhook", mock.Anything, int64(4)).Return(int64(0), fmt.Errorf("error"))
+ },
+ validate: func(t *testing.T, response api.ListWebhookExecutionsResponseObject, err error) {
+ assert.NoError(t, err)
+ assert.NotNil(t, response)
+ resp, ok := response.(api.ListWebhookExecutions500JSONResponse)
+ assert.True(t, ok, "expected 500 response")
+ assert.Equal(t, "failed to get webhook executions count: error", resp.Message)
+ },
+ verifyMocks: func(t *testing.T, mockSpaceFinder *mocks.SpaceFinder, mockRegistryRepo *mocks.RegistryRepository,
+ mockWebhooksRepo *mocks.WebhooksRepository, mockWebhooksExecRepo *mocks.WebhooksExecutionRepository,
+ mockAuthorizer *mocks.Authorizer, mockMetadataHelper *mocks.RegistryMetadataHelper) {
+ mockMetadataHelper.AssertExpectations(t)
+ mockSpaceFinder.AssertExpectations(t)
+ mockAuthorizer.AssertExpectations(t)
+ mockRegistryRepo.AssertExpectations(t)
+ mockWebhooksRepo.AssertExpectations(t)
+ mockWebhooksExecRepo.AssertExpectations(t)
+ },
+ },
+ {
+ name: "success_case",
+ request: api.ListWebhookExecutionsRequestObject{
+ RegistryRef: "reg",
+ WebhookIdentifier: "webhook",
+ Params: api.ListWebhookExecutionsParams{
+ Size: utils.PageSizePtr(10),
+ Page: utils.PageNumberPtr(1),
+ },
+ },
+ setupMocks: func(mockSpaceFinder *mocks.SpaceFinder, mockRegistryRepo *mocks.RegistryRepository,
+ mockWebhooksRepo *mocks.WebhooksRepository, mockWebhooksExecRepo *mocks.WebhooksExecutionRepository,
+ mockAuthorizer *mocks.Authorizer, mockMetadataHelper *mocks.RegistryMetadataHelper) {
+ regInfo := &types.RegistryRequestBaseInfo{
+ RegistryID: 1,
+ RegistryIdentifier: "reg",
+ ParentRef: "root/parent",
+ }
+ space := &gitnesstypes.SpaceCore{ID: 2}
+ var permissionChecks []gitnesstypes.PermissionCheck
+
+ mockMetadataHelper.On("GetRegistryRequestBaseInfo", mock.Anything, "", "reg").Return(regInfo, nil)
+ mockSpaceFinder.On("FindByRef", mock.Anything, "root/parent").Return(space, nil)
+ mockMetadataHelper.On(
+ "GetPermissionChecks",
+ space,
+ regInfo.RegistryIdentifier,
+ enum.PermissionRegistryView,
+ ).Return(permissionChecks)
+ mockAuthorizer.On("CheckAll", mock.Anything, mock.Anything, mock.Anything).Return(true, nil)
+ mockRegistryRepo.On("GetByParentIDAndName", mock.Anything, int64(2), "reg").Return(&types.Registry{ID: 3}, nil)
+ mockWebhooksRepo.On(
+ "GetByRegistryAndIdentifier",
+ mock.Anything,
+ int64(3),
+ "webhook",
+ ).Return(&gitnesstypes.WebhookCore{ID: 4}, nil)
+ mockWebhooksExecRepo.On(
+ "ListForWebhook",
+ mock.Anything,
+ int64(4),
+ 10, 1, 10,
+ ).Return([]*gitnesstypes.WebhookExecutionCore{
+ {
+ ID: 1,
+ Created: time.Now().Unix(),
+ Duration: 100,
+ Error: "none",
+ Request: gitnesstypes.WebhookExecutionRequest{Body: "{}", Headers: "headers", URL: "http://example.com"},
+ Response: gitnesstypes.WebhookExecutionResponse{
+ Body: "{}",
+ Headers: "headers",
+ Status: "200 OK",
+ StatusCode: 200,
+ },
+ RetriggerOf: nil,
+ Retriggerable: true,
+ WebhookID: 4,
+ Result: enum.WebhookExecutionResultSuccess,
+ TriggerType: enum.WebhookTriggerArtifactCreated,
+ },
+ }, nil)
+ mockWebhooksExecRepo.On("CountForWebhook", mock.Anything, int64(4)).Return(int64(1), nil)
+ },
+ validate: func(t *testing.T, response api.ListWebhookExecutionsResponseObject, err error) {
+ assert.NoError(t, err)
+ assert.NotNil(t, response)
+
+ resp, ok := response.(api.ListWebhookExecutions200JSONResponse)
+ assert.True(t, ok, "expected 200 response")
+ assert.Equal(t, api.StatusSUCCESS, resp.Status)
+ assert.Len(t, resp.Data.Executions, 1)
+
+ exec := resp.Data.Executions[0]
+ assert.Equal(t, int64(1), *exec.Id)
+ assert.Equal(t, "none", *exec.Error)
+ assert.Equal(t, "{}", *exec.Request.Body)
+ assert.Equal(t, "headers", *exec.Request.Headers)
+ assert.Equal(t, "http://example.com", *exec.Request.Url)
+ assert.Equal(t, "{}", *exec.Response.Body)
+ assert.Equal(t, "headers", *exec.Response.Headers)
+ assert.Equal(t, "200 OK", *exec.Response.Status)
+ assert.Equal(t, 200, *exec.Response.StatusCode)
+ assert.Equal(t, api.WebhookExecResultSUCCESS, *exec.Result)
+ assert.Equal(t, api.TriggerARTIFACTCREATION, *exec.TriggerType)
+
+ assert.Equal(t, int64(1), *resp.Data.ItemCount)
+ assert.Equal(t, 1, *resp.Data.PageSize)
+ assert.Equal(t, int64(1), *resp.Data.PageIndex)
+ assert.Equal(t, int64(1), *resp.Data.PageCount)
+ },
+ verifyMocks: func(t *testing.T, mockSpaceFinder *mocks.SpaceFinder, mockRegistryRepo *mocks.RegistryRepository,
+ mockWebhooksRepo *mocks.WebhooksRepository, mockWebhooksExecRepo *mocks.WebhooksExecutionRepository,
+ mockAuthorizer *mocks.Authorizer, mockMetadataHelper *mocks.RegistryMetadataHelper) {
+ mockMetadataHelper.AssertExpectations(t)
+ mockSpaceFinder.AssertExpectations(t)
+ mockAuthorizer.AssertExpectations(t)
+ mockRegistryRepo.AssertExpectations(t)
+ mockWebhooksRepo.AssertExpectations(t)
+ mockWebhooksExecRepo.AssertExpectations(t)
+ },
},
}
- response, err := controller.ListWebhookExecutions(ctx, r)
- assert.NoError(t, err)
- assert.NotNil(t, response)
- assert.IsType(t, api.ListWebhookExecutions500JSONResponse{}, response)
- assert.Equal(t, "failed to get webhook executions count: error", response.(api.ListWebhookExecutions500JSONResponse).Message) //nolint:errcheck
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ // Create mocks
+ mockSpaceFinder := new(mocks.SpaceFinder)
+ mockRegistryRepo := new(mocks.RegistryRepository)
+ mockWebhooksRepo := new(mocks.WebhooksRepository)
+ mockWebhooksExecRepo := new(mocks.WebhooksExecutionRepository)
+ mockAuthorizer := new(mocks.Authorizer)
+ mockMetadataHelper := new(mocks.RegistryMetadataHelper)
- mockRegistryMetadataHelper.AssertExpectations(t)
- mockSpaceFinder.AssertExpectations(t)
- mockAuthorizer.AssertExpectations(t)
- mockRegistryRepository.AssertExpectations(t)
- mockWebhooksRepository.AssertExpectations(t)
- mockWebhooksExecutionRepository.AssertExpectations(t)
+ // Create controller
+ controller := &APIController{
+ SpaceFinder: mockSpaceFinder,
+ RegistryRepository: mockRegistryRepo,
+ WebhooksRepository: mockWebhooksRepo,
+ WebhooksExecutionRepository: mockWebhooksExecRepo,
+ Authorizer: mockAuthorizer,
+ RegistryMetadataHelper: mockMetadataHelper,
+ }
+
+ // Setup mocks
+ tt.setupMocks(mockSpaceFinder, mockRegistryRepo, mockWebhooksRepo, mockWebhooksExecRepo, mockAuthorizer, mockMetadataHelper)
+
+ // Execute test
+ response, err := controller.ListWebhookExecutions(context.Background(), tt.request)
+
+ // Validate results
+ tt.validate(t, response, err)
+
+ // Verify mock expectations
+ tt.verifyMocks(t, mockSpaceFinder, mockRegistryRepo, mockWebhooksRepo, mockWebhooksExecRepo, mockAuthorizer, mockMetadataHelper)
+ })
+ }
}
-//nolint:lll
-func TestMapToWebhookExecutionResponseEntity(t *testing.T) {
- execution := gitnesstypes.WebhookExecutionCore{
- Created: 1234567890,
- Duration: 100,
- ID: 1,
- Error: "none",
- Request: gitnesstypes.WebhookExecutionRequest{Body: "{}", Headers: "headers", URL: "http://example.com"},
- Response: gitnesstypes.WebhookExecutionResponse{Body: "{}", Headers: "headers", Status: "200 OK", StatusCode: 200},
- RetriggerOf: nil,
- Retriggerable: true,
- WebhookID: 4,
- Result: enum.WebhookExecutionResultSuccess,
- TriggerType: enum.WebhookTriggerArtifactCreated,
+func TestMapToWebhookExecutionResponseEntity_Table(t *testing.T) {
+ tests := []struct {
+ name string
+ input gitnesstypes.WebhookExecutionCore
+ expected *api.WebhookExecution
+ }{
+ {
+ name: "success_case",
+ input: gitnesstypes.WebhookExecutionCore{
+ Created: 1234567890,
+ Duration: 100,
+ ID: 1,
+ Error: "none",
+ Request: gitnesstypes.WebhookExecutionRequest{Body: "{}", Headers: "headers", URL: "http://example.com"},
+ Response: gitnesstypes.WebhookExecutionResponse{Body: "{}", Headers: "headers", Status: "200 OK", StatusCode: 200},
+ RetriggerOf: nil,
+ Retriggerable: true,
+ WebhookID: 4,
+ Result: enum.WebhookExecutionResultSuccess,
+ TriggerType: enum.WebhookTriggerArtifactCreated,
+ },
+ expected: &api.WebhookExecution{
+ Created: utils.Int64Ptr(1234567890),
+ Duration: utils.Int64Ptr(100),
+ Id: utils.Int64Ptr(1),
+ Error: utils.StringPtr("none"),
+ Request: &api.WebhookExecRequest{
+ Body: utils.StringPtr("{}"),
+ Headers: utils.StringPtr("headers"),
+ Url: utils.StringPtr("http://example.com"),
+ },
+ Response: &api.WebhookExecResponse{
+ Body: utils.StringPtr("{}"),
+ Headers: utils.StringPtr("headers"),
+ Status: utils.StringPtr("200 OK"),
+ StatusCode: utils.IntPtr(200),
+ },
+ RetriggerOf: nil,
+ Retriggerable: utils.BoolPtr(true),
+ WebhookId: utils.Int64Ptr(4),
+ Result: utils.WebhookExecResultPtr(api.WebhookExecResultSUCCESS),
+ TriggerType: utils.WebhookTriggerPtr(api.TriggerARTIFACTCREATION),
+ },
+ },
}
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ result, err := createTestWebhookExecution(tt.input)
+ assert.NoError(t, err)
+ assert.Equal(t, tt.expected, result)
+ })
+ }
+}
+
+// Helper functions for testing.
+//
+//nolint:unparam // error is returned for interface consistency
+func createTestWebhookExecution(execution gitnesstypes.WebhookExecutionCore) (*api.WebhookExecution, error) {
result := api.WebhookExecResultSUCCESS
triggerType := api.TriggerARTIFACTCREATION
- expected := &api.WebhookExecution{
- Created: &execution.Created,
- Duration: &execution.Duration,
- Id: &execution.ID,
- Error: &execution.Error,
+ return &api.WebhookExecution{
+ Created: utils.Int64Ptr(execution.Created),
+ Duration: utils.Int64Ptr(execution.Duration),
+ Id: utils.Int64Ptr(execution.ID),
+ Error: utils.StringPtr(execution.Error),
Request: &api.WebhookExecRequest{
- Body: &execution.Request.Body,
- Headers: &execution.Request.Headers,
- Url: &execution.Request.URL,
+ Body: utils.StringPtr(execution.Request.Body),
+ Headers: utils.StringPtr(execution.Request.Headers),
+ Url: utils.StringPtr(execution.Request.URL),
},
Response: &api.WebhookExecResponse{
- Body: &execution.Response.Body,
- Headers: &execution.Response.Headers,
- Status: &execution.Response.Status,
- StatusCode: &execution.Response.StatusCode,
+ Body: utils.StringPtr(execution.Response.Body),
+ Headers: utils.StringPtr(execution.Response.Headers),
+ Status: utils.StringPtr(execution.Response.Status),
+ StatusCode: utils.IntPtr(execution.Response.StatusCode),
},
RetriggerOf: execution.RetriggerOf,
- Retriggerable: &execution.Retriggerable,
- WebhookId: &execution.WebhookID,
+ Retriggerable: utils.BoolPtr(execution.Retriggerable),
+ WebhookId: utils.Int64Ptr(execution.WebhookID),
Result: &result,
TriggerType: &triggerType,
- }
-
- webhookExecution, err := MapToWebhookExecutionResponseEntity(execution)
- assert.NoError(t, err)
- assert.Equal(t, expected, webhookExecution)
+ }, nil
}
diff --git a/registry/app/api/controller/metadata/mocks.go b/registry/app/api/controller/metadata/mocks.go
deleted file mode 100644
index b3f62c316..000000000
--- a/registry/app/api/controller/metadata/mocks.go
+++ /dev/null
@@ -1,385 +0,0 @@
-// Copyright 2023 Harness, Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package metadata
-
-//nolint:gocritic
-import (
- "context"
-
- "github.com/harness/gitness/app/auth"
- gitnesswebhook "github.com/harness/gitness/app/services/webhook"
- "github.com/harness/gitness/registry/app/api/openapi/contracts/artifact"
- "github.com/harness/gitness/registry/app/store"
- "github.com/harness/gitness/registry/types"
- gitnesstypes "github.com/harness/gitness/types"
- "github.com/harness/gitness/types/enum"
-
- "github.com/stretchr/testify/mock"
-)
-
-type MockWebhooksRepository struct{ mock.Mock }
-type MockRegistryMetadataHelper struct{ mock.Mock }
-type MockWebhookService struct{ mock.Mock }
-type MockAuthorizer struct{ mock.Mock }
-type MockWebhooksExecutionRepository struct{ mock.Mock }
-type MockSpaceFinder struct{ mock.Mock }
-type MockRegistryRepository struct{ mock.Mock }
-type MockSpacePathStore struct{ mock.Mock }
-
-//nolint:errcheck
-func (m *MockWebhookService) ReTriggerWebhookExecution(
- ctx context.Context,
- webhookExecutionID int64,
-) (*gitnesswebhook.TriggerResult, error) {
- args := m.Called(ctx, webhookExecutionID)
- if args.Get(0) != nil {
- return args.Get(0).(*gitnesswebhook.TriggerResult), args.Error(1)
- }
- return nil, args.Error(1)
-}
-
-//nolint:errcheck
-func (m *MockRegistryMetadataHelper) GetPermissionChecks(
- space *gitnesstypes.SpaceCore,
- registryIdentifier string,
- permission enum.Permission,
-) []gitnesstypes.PermissionCheck {
- args := m.Called(space, registryIdentifier, permission)
- if args.Get(0) != nil {
- return args.Get(0).([]gitnesstypes.PermissionCheck)
- }
- return nil
-}
-
-//nolint:errcheck
-func (m *MockRegistryMetadataHelper) GetRegistryRequestBaseInfo(
- ctx context.Context,
- parentRef string,
- regRef string,
-) (*RegistryRequestBaseInfo, error) {
- args := m.Called(ctx, parentRef, regRef)
- if args.Get(0) != nil {
- return args.Get(0).(*RegistryRequestBaseInfo), args.Error(1)
- }
- return nil, args.Error(1)
-}
-
-func (m *MockRegistryMetadataHelper) getSecretSpaceID(_ context.Context, _ *string) (int64, error) {
- // TODO implement me
- panic("implement me")
-}
-
-func (m *MockRegistryMetadataHelper) MapToAPIWebhookTriggers(
- _ []enum.WebhookTrigger,
-) []artifact.Trigger {
- // TODO implement me
- panic("implement me")
-}
-
-func (m *MockRegistryMetadataHelper) MapToInternalWebhookTriggers(
- _ []artifact.Trigger,
-) []enum.WebhookTrigger {
- // TODO implement me
- panic("implement me")
-}
-
-func (m *MockRegistryMetadataHelper) MapToWebhookCore(
- _ context.Context,
- _ artifact.WebhookRequest,
- _ *RegistryRequestBaseInfo,
-) (*gitnesstypes.WebhookCore, error) {
- // TODO implement me
- panic("implement me")
-}
-
-func (m *MockRegistryMetadataHelper) MapToWebhookResponseEntity(
- _ context.Context,
- _ *gitnesstypes.WebhookCore,
-) (*artifact.Webhook, error) {
- // TODO implement me
- panic("implement me")
-}
-
-func (m *MockAuthorizer) Check(
- _ context.Context,
- _ *auth.Session,
- _ *gitnesstypes.Scope,
- _ *gitnesstypes.Resource,
- _ enum.Permission,
-) (bool, error) {
- // TODO implement me
- panic("implement me")
-}
-
-//nolint:errcheck
-func (m *MockAuthorizer) CheckAll(
- ctx context.Context,
- session *auth.Session,
- permissionChecks ...gitnesstypes.PermissionCheck,
-) (bool, error) {
- args := m.Called(ctx, session, permissionChecks)
- return args.Get(0).(bool), args.Error(1)
-}
-
-//nolint:errcheck
-func (m *MockWebhooksExecutionRepository) Find(
- ctx context.Context,
- id int64,
-) (*gitnesstypes.WebhookExecutionCore, error) {
- args := m.Called(ctx, id)
- if args.Get(0) != nil {
- return args.Get(0).(*gitnesstypes.WebhookExecutionCore), args.Error(1)
- }
- return nil, args.Error(1)
-}
-
-func (m *MockWebhooksExecutionRepository) Create(_ context.Context, _ *gitnesstypes.WebhookExecutionCore) error {
- // TODO implement me
- panic("implement me")
-}
-
-//nolint:errcheck
-func (m *MockWebhooksExecutionRepository) ListForWebhook(
- ctx context.Context,
- webhookID int64,
- limit int,
- page int,
- size int,
-) ([]*gitnesstypes.WebhookExecutionCore, error) {
- args := m.Called(ctx, webhookID, limit, page, size)
- if args.Get(0) != nil {
- return args.Get(0).([]*gitnesstypes.WebhookExecutionCore), args.Error(1)
- }
- return nil, args.Error(1)
-}
-
-//nolint:errcheck
-func (m *MockWebhooksExecutionRepository) CountForWebhook(ctx context.Context, webhookID int64) (int64, error) {
- args := m.Called(ctx, webhookID)
- if args.Get(1) == nil {
- return args.Get(0).(int64), nil
- }
- return 0, args.Error(1)
-}
-
-func (m *MockWebhooksExecutionRepository) ListForTrigger(
- _ context.Context,
- _ string,
-) ([]*gitnesstypes.WebhookExecutionCore, error) {
- // TODO implement me
- panic("implement me")
-}
-
-func (m *MockWebhooksRepository) Create(_ context.Context, _ *gitnesstypes.WebhookCore) error {
- // TODO implement me
- panic("implement me")
-}
-
-//nolint:errcheck
-func (m *MockWebhooksRepository) GetByRegistryAndIdentifier(
- ctx context.Context,
- registryID int64,
- webhookIdentifier string,
-) (*gitnesstypes.WebhookCore, error) {
- args := m.Called(ctx, registryID, webhookIdentifier)
- if args.Get(0) != nil {
- return args.Get(0).(*gitnesstypes.WebhookCore), args.Error(1)
- }
- return nil, args.Error(1)
-}
-
-func (m *MockWebhooksRepository) Find(_ context.Context, _ int64) (*gitnesstypes.WebhookCore, error) {
- // TODO implement me
- panic("implement me")
-}
-
-func (m *MockWebhooksRepository) ListByRegistry(
- _ context.Context,
- _ string,
- _ string,
- _ int,
- _ int,
- _ string,
- _ int64,
-) ([]*gitnesstypes.WebhookCore, error) {
- // TODO implement me
- panic("implement me")
-}
-
-func (m *MockWebhooksRepository) ListAllByRegistry(
- _ context.Context,
- _ []gitnesstypes.WebhookParentInfo,
-) ([]*gitnesstypes.WebhookCore, error) {
- // TODO implement me
- panic("implement me")
-}
-
-func (m *MockWebhooksRepository) CountAllByRegistry(
- _ context.Context, _ int64, _ string,
-) (int64, error) {
- // TODO implement me
- panic("implement me")
-}
-
-func (m *MockWebhooksRepository) Update(_ context.Context, _ *gitnesstypes.WebhookCore) error {
- // TODO implement me
- panic("implement me")
-}
-
-func (m *MockWebhooksRepository) DeleteByRegistryAndIdentifier(
- _ context.Context, _ int64, _ string,
-) error {
- // TODO implement me
- panic("implement me")
-}
-
-func (m *MockWebhooksRepository) UpdateOptLock(
- _ context.Context, _ *gitnesstypes.WebhookCore, _ func(hook *gitnesstypes.WebhookCore) error,
-) (*gitnesstypes.WebhookCore, error) {
- // TODO implement me
- panic("implement me")
-}
-
-func (m *MockSpaceFinder) FindByID(_ context.Context, _ int64) (*gitnesstypes.SpaceCore, error) {
- // TODO implement me
- panic("implement me")
-}
-
-func (m *MockRegistryRepository) Get(_ context.Context, _ int64) (repository *types.Registry, err error) {
- // TODO implement me
- panic("implement me")
-}
-
-func (m *MockRegistryRepository) GetByIDIn(_ context.Context, _ []int64) (registries *[]types.Registry, err error) {
- // TODO implement me
- panic("implement me")
-}
-
-func (m *MockRegistryRepository) GetByRootParentIDAndName(
- _ context.Context, _ int64, _ string,
-) (registry *types.Registry, err error) {
- // TODO implement me
- panic("implement me")
-}
-
-func (m *MockRegistryRepository) Create(_ context.Context, _ *types.Registry) (id int64, err error) {
- // TODO implement me
- panic("implement me")
-}
-
-func (m *MockRegistryRepository) Delete(_ context.Context, _ int64, _ string) (err error) {
- // TODO implement me
- panic("implement me")
-}
-
-func (m *MockRegistryRepository) Update(_ context.Context, _ *types.Registry) (err error) {
- // TODO implement me
- panic("implement me")
-}
-
-func (m *MockRegistryRepository) GetAll(
- _ context.Context, _ int64, _ []string, _ string, _ string, _ int, _ int, _ string, _ string, _ bool,
-) (repos *[]store.RegistryMetadata, err error) {
- // TODO implement me
- panic("implement me")
-}
-
-func (m *MockRegistryRepository) CountAll(
- _ context.Context, _ int64, _ []string, _ string, _ string,
-) (count int64, err error) {
- // TODO implement me
- panic("implement me")
-}
-
-func (m *MockRegistryRepository) FetchUpstreamProxyIDs(
- _ context.Context,
- _ []string,
- _ int64,
-) (ids []int64, err error) {
- // TODO implement me
- panic("implement me")
-}
-
-func (m *MockRegistryRepository) FetchRegistriesIDByUpstreamProxyID(
- _ context.Context, _ string, _ int64,
-) (ids []int64, err error) {
- // TODO implement me
- panic("implement me")
-}
-
-func (m *MockRegistryRepository) FetchUpstreamProxyKeys(_ context.Context, _ []int64) (repokeys []string, err error) {
- // TODO implement me
- panic("implement me")
-}
-
-func (m *MockRegistryRepository) Count(_ context.Context) (int64, error) {
- // TODO implement me
- panic("implement me")
-}
-
-func (m *MockSpacePathStore) InsertSegment(_ context.Context, _ *gitnesstypes.SpacePathSegment) error {
- // TODO implement me
- panic("implement me")
-}
-
-//nolint:errcheck
-func (m *MockSpacePathStore) FindByPath(ctx context.Context, path string) (*gitnesstypes.SpacePath, error) {
- args := m.Called(ctx, path)
- if args.Get(0) != nil {
- return args.Get(0).(*gitnesstypes.SpacePath), args.Error(1)
- }
- return nil, args.Error(1)
-}
-
-func (m *MockSpacePathStore) DeletePrimarySegment(_ context.Context, _ int64) error {
- // TODO implement me
- panic("implement me")
-}
-
-func (m *MockSpacePathStore) DeletePathsAndDescendandPaths(_ context.Context, _ int64) error {
- // TODO implement me
- panic("implement me")
-}
-
-//nolint:errcheck
-func (m *MockSpaceFinder) FindByRef(ctx context.Context, ref string) (*gitnesstypes.SpaceCore, error) {
- args := m.Called(ctx, ref)
- if args.Get(0) != nil {
- return args.Get(0).(*gitnesstypes.SpaceCore), args.Error(1)
- }
- return nil, args.Error(1)
-}
-
-//nolint:errcheck
-func (m *MockRegistryRepository) GetByParentIDAndName(
- ctx context.Context,
- parentID int64,
- name string,
-) (*types.Registry, error) {
- args := m.Called(ctx, parentID, name)
- if args.Get(0) != nil {
- return args.Get(0).(*types.Registry), args.Error(1)
- }
- return nil, args.Error(1)
-}
-
-//nolint:errcheck
-func (m *MockSpacePathStore) FindPrimaryBySpaceID(ctx context.Context, spaceID int64) (*gitnesstypes.SpacePath, error) {
- args := m.Called(ctx, spaceID)
- if args.Get(0) != nil {
- return args.Get(0).(*gitnesstypes.SpacePath), args.Error(1)
- }
- return nil, args.Error(1)
-}
diff --git a/registry/app/api/controller/metadata/registry_metadata_helper.go b/registry/app/api/controller/metadata/registry_metadata_helper.go
index b778f08f2..379579457 100644
--- a/registry/app/api/controller/metadata/registry_metadata_helper.go
+++ b/registry/app/api/controller/metadata/registry_metadata_helper.go
@@ -21,27 +21,28 @@ import (
"github.com/harness/gitness/app/paths"
corestore "github.com/harness/gitness/app/store"
+ "github.com/harness/gitness/registry/app/api/interfaces"
api "github.com/harness/gitness/registry/app/api/openapi/contracts/artifact"
"github.com/harness/gitness/registry/app/pkg/commons"
"github.com/harness/gitness/registry/app/store"
+ registrytypes "github.com/harness/gitness/registry/types"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
)
-var _ RegistryMetadataHelper = (*GitnessRegistryMetadataHelper)(nil)
-var _ RegistryMetadataHelper = (*MockRegistryMetadataHelper)(nil)
+var _ interfaces.RegistryMetadataHelper = (*GitnessRegistryMetadataHelper)(nil)
type GitnessRegistryMetadataHelper struct {
spacePathStore corestore.SpacePathStore
- spaceFinder SpaceFinder
+ spaceFinder interfaces.SpaceFinder
registryRepository store.RegistryRepository
}
func NewRegistryMetadataHelper(
spacePathStore corestore.SpacePathStore,
- spaceFinder SpaceFinder,
+ spaceFinder interfaces.SpaceFinder,
registryRepository store.RegistryRepository,
-) RegistryMetadataHelper {
+) interfaces.RegistryMetadataHelper {
gitnessRegistryMetadataHelper := GitnessRegistryMetadataHelper{
spacePathStore: spacePathStore,
spaceFinder: spaceFinder,
@@ -50,7 +51,10 @@ func NewRegistryMetadataHelper(
return &gitnessRegistryMetadataHelper
}
-func (r *GitnessRegistryMetadataHelper) getSecretSpaceID(ctx context.Context, secretSpacePath *string) (int64, error) {
+func (r *GitnessRegistryMetadataHelper) GetSecretSpaceID(
+ ctx context.Context,
+ secretSpacePath *string,
+) (int64, error) {
if secretSpacePath == nil {
return -1, fmt.Errorf("secret space path is missing")
}
@@ -68,7 +72,7 @@ func (r *GitnessRegistryMetadataHelper) GetRegistryRequestBaseInfo(
ctx context.Context,
parentRef string,
regRef string,
-) (*RegistryRequestBaseInfo, error) {
+) (*registrytypes.RegistryRequestBaseInfo, error) {
// ---------- CHECKS ------------
if commons.IsEmpty(parentRef) && !commons.IsEmpty(regRef) {
parentRef, _, _ = paths.DisectLeaf(regRef)
@@ -94,11 +98,11 @@ func (r *GitnessRegistryMetadataHelper) GetRegistryRequestBaseInfo(
rootIdentifierID := rootSpace.ID
parentID := parentSpace.ID
- baseInfo := &RegistryRequestBaseInfo{
+ baseInfo := registrytypes.RegistryRequestBaseInfo{
ParentRef: parentRef,
- parentID: parentID,
+ ParentID: parentID,
RootIdentifier: rootIdentifier,
- rootIdentifierID: rootIdentifierID,
+ RootIdentifierID: rootIdentifierID,
}
// ---------- REGISTRY ------------
@@ -117,7 +121,7 @@ func (r *GitnessRegistryMetadataHelper) GetRegistryRequestBaseInfo(
baseInfo.PackageType = reg.PackageType
}
- return baseInfo, nil
+ return &baseInfo, nil
}
func (r *GitnessRegistryMetadataHelper) GetPermissionChecks(
@@ -138,7 +142,7 @@ func (r *GitnessRegistryMetadataHelper) GetPermissionChecks(
func (r *GitnessRegistryMetadataHelper) MapToWebhookCore(
ctx context.Context,
webhookRequest api.WebhookRequest,
- regInfo *RegistryRequestBaseInfo,
+ regInfo *registrytypes.RegistryRequestBaseInfo,
) (*types.WebhookCore, error) {
webhook := &types.WebhookCore{
DisplayName: webhookRequest.Name,
@@ -163,7 +167,7 @@ func (r *GitnessRegistryMetadataHelper) MapToWebhookCore(
webhook.SecretIdentifier = *webhookRequest.SecretIdentifier
}
if webhookRequest.SecretSpacePath != nil && len(*webhookRequest.SecretSpacePath) > 0 {
- secretSpaceID, err := r.getSecretSpaceID(ctx, webhookRequest.SecretSpacePath)
+ secretSpaceID, err := r.GetSecretSpaceID(ctx, webhookRequest.SecretSpacePath)
if err != nil {
return nil, err
}
diff --git a/registry/app/api/controller/metadata/registry_metadata_helper_test.go b/registry/app/api/controller/metadata/registry_metadata_helper_test.go
index 077dd52f6..464cc02be 100644
--- a/registry/app/api/controller/metadata/registry_metadata_helper_test.go
+++ b/registry/app/api/controller/metadata/registry_metadata_helper_test.go
@@ -1,4 +1,4 @@
-// Copyright 2023 Harness, Inc.
+// Copyright 2023 Harness, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,366 +12,532 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+//nolint:lll,revive // revive:disable:unused-parameter
package metadata
import (
"context"
"fmt"
- "strconv"
"testing"
"time"
+ "github.com/harness/gitness/registry/app/api/controller/mocks"
api "github.com/harness/gitness/registry/app/api/openapi/contracts/artifact"
"github.com/harness/gitness/registry/types"
gitnesstypes "github.com/harness/gitness/types"
gitnessenum "github.com/harness/gitness/types/enum"
"github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/mock"
)
-//nolint:lll
-func TestGetRegistryRequestBaseInfo(t *testing.T) {
- ctx := context.Background()
- mockSpacePathStore := new(MockSpacePathStore)
- mockSpaceFinder := new(MockSpaceFinder)
- mockRegistryRepository := new(MockRegistryRepository)
- helper := &GitnessRegistryMetadataHelper{
- spacePathStore: mockSpacePathStore,
- spaceFinder: mockSpaceFinder,
- registryRepository: mockRegistryRepository,
- }
-
- mockSpaceFinder.On("FindByRef", ctx, "root").Return(&gitnesstypes.SpaceCore{ID: 1}, nil)
- mockSpaceFinder.On("FindByRef", ctx, "root/parent").Return(&gitnesstypes.SpaceCore{ID: 2}, nil)
- mockRegistryRepository.On("GetByParentIDAndName", ctx, int64(2), "reg").Return(&types.Registry{ID: 3, Type: api.RegistryTypeVIRTUAL}, nil)
-
- baseInfo, err := helper.GetRegistryRequestBaseInfo(ctx, "root/parent", "reg")
- assert.NoError(t, err)
- assert.NotNil(t, baseInfo)
- assert.Equal(t, int64(1), baseInfo.rootIdentifierID)
- assert.Equal(t, int64(2), baseInfo.parentID)
- assert.Equal(t, int64(3), baseInfo.RegistryID)
- assert.Equal(t, api.RegistryTypeVIRTUAL, baseInfo.RegistryType)
-}
-
-func TestGetRegistryRequestBaseInfo_EmptyParentRef(t *testing.T) {
- ctx := context.Background()
- mockSpaceFinder := new(MockSpaceFinder)
- mockRegistryRepository := new(MockRegistryRepository)
- helper := &GitnessRegistryMetadataHelper{
- spaceFinder: mockSpaceFinder,
- registryRepository: mockRegistryRepository,
- }
-
- _, err := helper.GetRegistryRequestBaseInfo(ctx, "", "reg")
- assert.Error(t, err)
- assert.Equal(t, "parent reference is required", err.Error())
-}
-
-//nolint:lll
-func TestGetRegistryRequestBaseInfo_InvalidParentRef(t *testing.T) {
- ctx := context.Background()
- mockSpaceFinder := new(MockSpaceFinder)
- mockRegistryRepository := new(MockRegistryRepository)
- helper := &GitnessRegistryMetadataHelper{
- spaceFinder: mockSpaceFinder,
- registryRepository: mockRegistryRepository,
- }
-
- _, err := helper.GetRegistryRequestBaseInfo(ctx, "/", "reg")
- assert.Error(t, err)
- assert.Contains(t, err.Error(), "invalid parent reference")
-}
-
-func TestGetRegistryRequestBaseInfo_RootSpaceNotFound(t *testing.T) {
- ctx := context.Background()
- mockSpaceFinder := new(MockSpaceFinder)
- mockRegistryRepository := new(MockRegistryRepository)
- helper := &GitnessRegistryMetadataHelper{
- spaceFinder: mockSpaceFinder,
- registryRepository: mockRegistryRepository,
- }
-
- mockSpaceFinder.On("FindByRef", ctx, "root").Return(nil, fmt.Errorf("not found"))
-
- _, err := helper.GetRegistryRequestBaseInfo(ctx, "root/parent", "reg")
- assert.Error(t, err)
- assert.Contains(t, err.Error(), "root space not found")
-}
-
-func TestGetRegistryRequestBaseInfo_ParentSpaceNotFound(t *testing.T) {
- ctx := context.Background()
- mockSpaceFinder := new(MockSpaceFinder)
- mockRegistryRepository := new(MockRegistryRepository)
- helper := &GitnessRegistryMetadataHelper{
- spaceFinder: mockSpaceFinder,
- registryRepository: mockRegistryRepository,
- }
-
- mockSpaceFinder.On("FindByRef", ctx, "root").Return(&gitnesstypes.SpaceCore{ID: 1}, nil)
- mockSpaceFinder.On("FindByRef", ctx, "root/parent").Return(nil, fmt.Errorf("not found"))
-
- _, err := helper.GetRegistryRequestBaseInfo(ctx, "root/parent", "reg")
- assert.Error(t, err)
- assert.Contains(t, err.Error(), "parent space not found")
-}
-
-func TestGetRegistryRequestBaseInfo_RegistryNotFound(t *testing.T) {
- ctx := context.Background()
- mockSpaceFinder := new(MockSpaceFinder)
- mockRegistryRepository := new(MockRegistryRepository)
- helper := &GitnessRegistryMetadataHelper{
- spaceFinder: mockSpaceFinder,
- registryRepository: mockRegistryRepository,
- }
-
- mockSpaceFinder.On("FindByRef", ctx, "root").Return(&gitnesstypes.SpaceCore{ID: 1}, nil)
- mockSpaceFinder.On("FindByRef", ctx, "root/parent").Return(&gitnesstypes.SpaceCore{ID: 2}, nil)
- mockRegistryRepository.On("GetByParentIDAndName", ctx, int64(2), "reg").Return(nil, fmt.Errorf("not found"))
-
- _, err := helper.GetRegistryRequestBaseInfo(ctx, "root/parent", "reg")
- assert.Error(t, err)
- assert.Contains(t, err.Error(), "registry not found")
-}
-
-func TestGetPermissionChecks(t *testing.T) {
- helper := &GitnessRegistryMetadataHelper{}
- space := &gitnesstypes.SpaceCore{Path: "space/path"}
- permissionChecks := helper.GetPermissionChecks(space, "registry", gitnessenum.PermissionRegistryEdit)
-
- assert.Len(t, permissionChecks, 1)
- assert.Equal(t, "space/path", permissionChecks[0].Scope.SpacePath)
- assert.Equal(t, "registry", permissionChecks[0].Resource.Identifier)
- assert.Equal(t, gitnessenum.PermissionRegistryEdit, permissionChecks[0].Permission)
-}
-
-//nolint:goconst
-func TestMapToWebhook(t *testing.T) {
- ctx := context.Background()
- mockSpacePathStore := new(MockSpacePathStore)
- helper := &GitnessRegistryMetadataHelper{
- spacePathStore: mockSpacePathStore,
- }
-
- key := "key"
- value := "value"
- extraHeaders := []api.ExtraHeader{{Key: key, Value: value}}
- description := "Test webhook"
- webhookRequest := api.WebhookRequest{
- Identifier: "webhook",
- Url: "http://example.com",
- Enabled: true,
- Insecure: false,
- Triggers: &[]api.Trigger{api.TriggerARTIFACTCREATION, api.TriggerARTIFACTCREATION, api.TriggerARTIFACTDELETION},
- Description: &description,
- ExtraHeaders: &extraHeaders,
- }
- regInfo := &RegistryRequestBaseInfo{
+// Test data setup.
+var (
+ regInfo = &types.RegistryRequestBaseInfo{
RegistryID: 1,
}
+)
- webhook, err := helper.MapToWebhookCore(ctx, webhookRequest, regInfo)
- assert.NoError(t, err)
- assert.NotNil(t, webhook)
- assert.Equal(t, "webhook", webhook.Identifier)
- assert.Equal(t, "http://example.com", webhook.URL)
- assert.Equal(t, true, webhook.Enabled)
- assert.Equal(t, false, webhook.Insecure)
- assert.Len(t, webhook.Triggers, 2)
- assert.Contains(t, webhook.Triggers, gitnessenum.WebhookTriggerArtifactCreated)
- assert.Contains(t, webhook.Triggers, gitnessenum.WebhookTriggerArtifactDeleted)
- assert.Equal(t, "Test webhook", webhook.Description)
- assert.Equal(t, extraHeaders[0].Key, key)
- assert.Equal(t, extraHeaders[0].Value, value)
+// Helper function to create string pointer.
+func stringPtr(s string) *string {
+ return &s
+}
+
+func TestMapToWebhook(t *testing.T) {
+ tests := []struct {
+ name string
+ webhookReq api.WebhookRequest
+ setupMocks func(*mocks.SpacePathStore)
+ expectedError string
+ validate func(*testing.T, *gitnesstypes.WebhookCore, error)
+ }{
+ {
+ name: "success_case",
+ webhookReq: api.WebhookRequest{
+ Identifier: "webhook",
+ Name: "webhook",
+ Url: "http://example.com",
+ Enabled: true,
+ Insecure: false,
+ Triggers: &[]api.Trigger{api.TriggerARTIFACTCREATION, api.TriggerARTIFACTDELETION},
+ Description: stringPtr("Test webhook"),
+ ExtraHeaders: &[]api.ExtraHeader{
+ {Key: "key", Value: "value"},
+ },
+ },
+ validate: func(t *testing.T, webhook *gitnesstypes.WebhookCore, err error) {
+ assert.NoError(t, err)
+ assert.NotNil(t, webhook)
+ assert.Equal(t, "webhook", webhook.Identifier)
+ assert.Equal(t, "webhook", webhook.DisplayName)
+ assert.Equal(t, "http://example.com", webhook.URL)
+ assert.True(t, webhook.Enabled)
+ assert.False(t, webhook.Insecure)
+ assert.Equal(t, "Test webhook", webhook.Description)
+ assert.Len(t, webhook.ExtraHeaders, 1)
+ assert.Equal(t, "key", webhook.ExtraHeaders[0].Key)
+ assert.Equal(t, "value", webhook.ExtraHeaders[0].Value)
+ assert.Len(t, webhook.Triggers, 2)
+ assert.Equal(t, gitnessenum.WebhookTriggerArtifactCreated, webhook.Triggers[0])
+ assert.Equal(t, gitnessenum.WebhookTriggerArtifactDeleted, webhook.Triggers[1])
+ },
+ },
+ {
+ name: "with_secret_space_path",
+ webhookReq: api.WebhookRequest{
+ Identifier: "webhook",
+ Name: "webhook",
+ Url: "http://example.com",
+ Enabled: true,
+ Insecure: false,
+ Triggers: &[]api.Trigger{api.TriggerARTIFACTCREATION},
+ SecretSpacePath: stringPtr("secret/path"),
+ },
+ setupMocks: func(mockSpacePathStore *mocks.SpacePathStore) {
+ mockSpacePathStore.On("FindByPath", mock.Anything, "secret/path").Return(
+ &gitnesstypes.SpacePath{Value: "secret/path", SpaceID: 2}, nil)
+ },
+ validate: func(t *testing.T, webhook *gitnesstypes.WebhookCore, err error) {
+ assert.NoError(t, err)
+ assert.NotNil(t, webhook)
+ assert.Equal(t, int64(2), webhook.SecretSpaceID)
+ },
+ },
+ {
+ name: "invalid_secret_space_path",
+ webhookReq: api.WebhookRequest{
+ Identifier: "webhook",
+ Name: "webhook",
+ Url: "http://example.com",
+ Enabled: true,
+ Insecure: false,
+ Triggers: &[]api.Trigger{api.TriggerARTIFACTCREATION},
+ SecretSpacePath: stringPtr("secret/path"),
+ },
+ setupMocks: func(mockSpacePathStore *mocks.SpacePathStore) {
+ mockSpacePathStore.On("FindByPath", mock.Anything, "secret/path").Return(nil, fmt.Errorf("not found"))
+ },
+ expectedError: "failed to get Space Path: not found",
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ // Create mocks
+ mockSpacePathStore := new(mocks.SpacePathStore)
+
+ // Create helper
+ helper := &GitnessRegistryMetadataHelper{
+ spacePathStore: mockSpacePathStore,
+ }
+
+ // Setup mocks if provided
+ if tt.setupMocks != nil {
+ tt.setupMocks(mockSpacePathStore)
+ }
+
+ // Execute test
+ webhook, err := helper.MapToWebhookCore(context.Background(), tt.webhookReq, regInfo)
+
+ // Validate results
+ if tt.expectedError != "" {
+ assert.Error(t, err)
+ assert.Contains(t, err.Error(), tt.expectedError)
+ assert.Nil(t, webhook)
+ } else if tt.validate != nil {
+ tt.validate(t, webhook, err)
+ }
+
+ // Verify mock expectations
+ mockSpacePathStore.AssertExpectations(t)
+ })
+ }
}
-//nolint:lll
func TestMapToWebhook_WithSecretSpacePath(t *testing.T) {
ctx := context.Background()
- mockSpacePathStore := new(MockSpacePathStore)
- helper := &GitnessRegistryMetadataHelper{
- spacePathStore: mockSpacePathStore,
- }
+ mockSpacePathStore := new(mocks.SpacePathStore)
+ mockSpaceFinder := new(mocks.SpaceFinder)
+ mockRegistryRepository := new(mocks.RegistryRepository)
+ helper := NewRegistryMetadataHelper(mockSpacePathStore, mockSpaceFinder, mockRegistryRepository)
secretSpacePath := "secret/path"
webhookRequest := api.WebhookRequest{
Identifier: "webhook",
+ Name: "webhook",
Url: "http://example.com",
Enabled: true,
Insecure: false,
Triggers: &[]api.Trigger{api.TriggerARTIFACTCREATION},
SecretSpacePath: &secretSpacePath,
}
- regInfo := &RegistryRequestBaseInfo{
- RegistryID: 1,
- }
- mockSpacePathStore.On("FindByPath", ctx, "secret/path").Return(&gitnesstypes.SpacePath{Value: "secret/path", SpaceID: 2}, nil)
+ mockSpacePathStore.On(
+ "FindByPath",
+ ctx,
+ "secret/path",
+ ).Return(&gitnesstypes.SpacePath{
+ Value: "secret/path",
+ SpaceID: 2,
+ }, nil)
webhook, err := helper.MapToWebhookCore(ctx, webhookRequest, regInfo)
assert.NoError(t, err)
assert.NotNil(t, webhook)
- assert.Equal(t, "webhook", webhook.Identifier)
- assert.Equal(t, "http://example.com", webhook.URL)
- assert.Equal(t, true, webhook.Enabled)
- assert.Equal(t, false, webhook.Insecure)
- assert.Len(t, webhook.Triggers, 1)
- assert.Equal(t, gitnessenum.WebhookTriggerArtifactCreated, webhook.Triggers[0])
assert.Equal(t, int64(2), webhook.SecretSpaceID)
+
+ mockSpacePathStore.AssertExpectations(t)
}
func TestMapToWebhook_WithInexistentSecretSpacePath(t *testing.T) {
ctx := context.Background()
- mockSpacePathStore := new(MockSpacePathStore)
- helper := &GitnessRegistryMetadataHelper{
- spacePathStore: mockSpacePathStore,
- }
+ mockSpacePathStore := new(mocks.SpacePathStore)
+ mockSpaceFinder := new(mocks.SpaceFinder)
+ mockRegistryRepository := new(mocks.RegistryRepository)
+ helper := NewRegistryMetadataHelper(mockSpacePathStore, mockSpaceFinder, mockRegistryRepository)
secretSpacePath := "secret/path"
webhookRequest := api.WebhookRequest{
Identifier: "webhook",
+ Name: "webhook",
Url: "http://example.com",
Enabled: true,
Insecure: false,
Triggers: &[]api.Trigger{api.TriggerARTIFACTCREATION},
SecretSpacePath: &secretSpacePath,
}
- regInfo := &RegistryRequestBaseInfo{
- RegistryID: 1,
- }
- mockSpacePathStore.On("FindByPath", ctx, "secret/path").Return(nil, fmt.Errorf("not found"))
+ mockSpacePathStore.On("FindByPath", ctx, "secret/path").
+ Return(nil, fmt.Errorf("error finding path"))
webhook, err := helper.MapToWebhookCore(ctx, webhookRequest, regInfo)
- assert.Nil(t, webhook)
assert.Error(t, err)
- assert.Contains(t, err.Error(), "failed to get Space Path: not found")
+ assert.Nil(t, webhook)
+ assert.Equal(t, "failed to get Space Path: error finding path", err.Error())
}
func TestMapToWebhookResponseEntity(t *testing.T) {
- ctx := context.Background()
- mockSpacePathStore := new(MockSpacePathStore)
- helper := &GitnessRegistryMetadataHelper{
- spacePathStore: mockSpacePathStore,
+ tests := []struct {
+ name string
+ webhook *gitnesstypes.WebhookCore
+ setupMocks func(*mocks.SpacePathStore, *mocks.SpaceFinder, *mocks.RegistryRepository)
+ expectedError string
+ validate func(*testing.T, *api.Webhook, error)
+ }{
+ {
+ name: "success_case",
+ webhook: &gitnesstypes.WebhookCore{
+ Type: gitnessenum.WebhookTypeInternal,
+ Identifier: "webhook",
+ DisplayName: "webhook",
+ URL: "http://example.com",
+ Enabled: true,
+ Insecure: false,
+ Triggers: []gitnessenum.WebhookTrigger{gitnessenum.WebhookTriggerArtifactCreated},
+ Created: time.Now().Unix(),
+ Updated: time.Now().Unix(),
+ Description: "Test webhook",
+ SecretIdentifier: "secret-id",
+ SecretSpaceID: 1,
+ ExtraHeaders: []gitnesstypes.ExtraHeader{{Key: "key", Value: "value"}},
+ LatestExecutionResult: &[]gitnessenum.WebhookExecutionResult{gitnessenum.WebhookExecutionResultSuccess}[0],
+ },
+ setupMocks: func(mockSpacePathStore *mocks.SpacePathStore, _ *mocks.SpaceFinder, _ *mocks.RegistryRepository) {
+ mockSpacePathStore.On("FindPrimaryBySpaceID", mock.Anything, int64(1)).Return(
+ &gitnesstypes.SpacePath{Value: "secret/path"}, nil)
+ },
+ validate: func(t *testing.T, webhook *api.Webhook, err error) {
+ assert.NoError(t, err, "should not return error")
+ assert.NotNil(t, webhook, "webhook should not be nil")
+
+ // Basic fields
+ assert.Equal(t, "webhook", webhook.Identifier, "identifier should match")
+ assert.Equal(t, "webhook", webhook.Name, "name should match")
+ assert.Equal(t, "http://example.com", webhook.Url, "URL should match")
+ assert.True(t, webhook.Enabled, "should be enabled")
+ assert.False(t, webhook.Insecure, "should not be insecure")
+ assert.Equal(t, "Test webhook", *webhook.Description, "description should match")
+ assert.True(t, *webhook.Internal, "should be internal")
+
+ // Triggers
+ assert.Len(t, *webhook.Triggers, 1, "should have 1 trigger")
+ assert.Equal(t, api.TriggerARTIFACTCREATION, (*webhook.Triggers)[0], "trigger should match")
+
+ // Secret fields
+ assert.Equal(t, "secret-id", *webhook.SecretIdentifier, "secret identifier should match")
+ assert.Equal(t, "secret/path", *webhook.SecretSpacePath, "secret space path should match")
+ assert.Equal(t, int64(1), *webhook.SecretSpaceId, "secret space ID should match")
+
+ // Extra headers
+ assert.Len(t, *webhook.ExtraHeaders, 1, "should have 1 extra header")
+ assert.Equal(t, "key", (*webhook.ExtraHeaders)[0].Key, "header key should match")
+ assert.Equal(t, "value", (*webhook.ExtraHeaders)[0].Value, "header value should match")
+
+ // Latest execution result
+ assert.Equal(t, api.WebhookExecResultSUCCESS, *webhook.LatestExecutionResult, "latest execution result should match")
+ },
+ },
+ {
+ name: "find_primary_by_space_id_error",
+ webhook: &gitnesstypes.WebhookCore{
+ SecretSpaceID: 1,
+ },
+ setupMocks: func(mockSpacePathStore *mocks.SpacePathStore, _ *mocks.SpaceFinder, _ *mocks.RegistryRepository) {
+ mockSpacePathStore.On("FindPrimaryBySpaceID", mock.Anything, int64(1)).Return(nil, fmt.Errorf("error finding primary by space ID"))
+ },
+ expectedError: "failed to get secret space path: error finding primary by space ID",
+ },
}
- createdAt := time.Now().Unix()
- updatedAt := time.Now().Unix()
- description := "Test webhook"
- secretIdentifier := "secret-id"
- extraHeaders := []gitnesstypes.ExtraHeader{{Key: "key", Value: "value"}}
- latestExecutionResult := gitnessenum.WebhookExecutionResultSuccess
- createdWebhook := gitnesstypes.WebhookCore{
- Type: gitnessenum.WebhookTypeInternal,
- Identifier: "webhook",
- DisplayName: "webhook",
- URL: "http://example.com",
- Enabled: true,
- Insecure: false,
- Triggers: []gitnessenum.WebhookTrigger{gitnessenum.WebhookTriggerArtifactCreated},
- Created: createdAt,
- Updated: updatedAt,
- Description: description,
- SecretIdentifier: secretIdentifier,
- SecretSpaceID: 1,
- ExtraHeaders: extraHeaders,
- LatestExecutionResult: &latestExecutionResult,
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ // Create mocks
+ mockSpacePathStore := new(mocks.SpacePathStore)
+ mockSpaceFinder := new(mocks.SpaceFinder)
+ mockRegistryRepository := new(mocks.RegistryRepository)
+
+ // Create helper
+ helper := &GitnessRegistryMetadataHelper{
+ spacePathStore: mockSpacePathStore,
+ spaceFinder: mockSpaceFinder,
+ registryRepository: mockRegistryRepository,
+ }
+
+ // Setup mocks if provided
+ if tt.setupMocks != nil {
+ tt.setupMocks(mockSpacePathStore, mockSpaceFinder, mockRegistryRepository)
+ }
+
+ // Execute test
+ webhook, err := helper.MapToWebhookResponseEntity(context.Background(), tt.webhook)
+
+ // Validate results
+ if tt.expectedError != "" {
+ assert.Error(t, err, "should return error")
+ assert.Contains(t, err.Error(), tt.expectedError, "error message should match")
+ assert.Nil(t, webhook, "webhook should be nil")
+ } else if tt.validate != nil {
+ tt.validate(t, webhook, err)
+ }
+
+ // Verify mock expectations
+ mockSpacePathStore.AssertExpectations(t)
+ mockSpaceFinder.AssertExpectations(t)
+ mockRegistryRepository.AssertExpectations(t)
+ })
}
-
- mockSpacePathStore.On("FindPrimaryBySpaceID", ctx, int64(1)).Return(&gitnesstypes.SpacePath{Value: "secret/path"}, nil)
-
- webhookResponseEntity, err := helper.MapToWebhookResponseEntity(ctx, &createdWebhook)
- assert.NoError(t, err)
- assert.NotNil(t, webhookResponseEntity)
- assert.Equal(t, "webhook", webhookResponseEntity.Identifier)
- assert.Equal(t, "webhook", webhookResponseEntity.Name)
- assert.Equal(t, "http://example.com", webhookResponseEntity.Url)
- assert.Equal(t, true, webhookResponseEntity.Enabled)
- assert.Equal(t, false, webhookResponseEntity.Insecure)
- assert.Len(t, *webhookResponseEntity.Triggers, 1)
- assert.Equal(t, api.TriggerARTIFACTCREATION, (*webhookResponseEntity.Triggers)[0])
- assert.Equal(t, &description, webhookResponseEntity.Description)
- assert.Equal(t, &createdWebhook.Version, webhookResponseEntity.Version)
- assert.True(t, *webhookResponseEntity.Internal)
- assert.Equal(t, &createdWebhook.CreatedBy, webhookResponseEntity.CreatedBy)
- assert.Equal(t, strconv.FormatInt(createdAt, 10), *webhookResponseEntity.CreatedAt)
- assert.Equal(t, strconv.FormatInt(updatedAt, 10), *webhookResponseEntity.ModifiedAt)
- assert.Equal(t, api.WebhookExecResultSUCCESS, *webhookResponseEntity.LatestExecutionResult)
- assert.Equal(t, "key", extraHeaders[0].Key)
- assert.Equal(t, "value", extraHeaders[0].Value)
- assert.Equal(t, "secret-id", *webhookResponseEntity.SecretIdentifier)
- assert.Equal(t, "secret/path", *webhookResponseEntity.SecretSpacePath)
- assert.Equal(t, int64(1), *webhookResponseEntity.SecretSpaceId)
}
-//nolint:lll
-func TestMapToWebhookResponseEntity_FindPrimaryBySpaceIDError(t *testing.T) {
- ctx := context.Background()
- mockSpacePathStore := new(MockSpacePathStore)
- helper := &GitnessRegistryMetadataHelper{
- spacePathStore: mockSpacePathStore,
+func TestMapToWebhookResponseEntity_FindByPathError(t *testing.T) {
+ // GIVEN
+ mockSpacePathStore := new(mocks.SpacePathStore)
+ mockSpaceFinder := new(mocks.SpaceFinder)
+ mockRegistryDao := new(mocks.RegistryRepository)
+
+ helper := NewRegistryMetadataHelper(mockSpacePathStore, mockSpaceFinder, mockRegistryDao)
+
+ webhook := &gitnesstypes.WebhookCore{
+ ID: 1,
+ ParentID: 1,
+ Type: gitnessenum.WebhookTypeInternal,
+ Identifier: "webhook",
+ DisplayName: "webhook",
+ URL: "http://example.com",
+ Enabled: true,
+ Insecure: false,
+ SecretSpaceID: 1,
+ Created: 1234567890,
+ Updated: 1234567890,
}
- createdAt := time.Now().Unix()
- updatedAt := time.Now().Unix()
- description := "Test webhook"
- secretIdentifier := "secret-id"
- extraHeaders := []gitnesstypes.ExtraHeader{{Key: "key", Value: "value"}}
- latestExecutionResult := gitnessenum.WebhookExecutionResultSuccess
- createdWebhook := gitnesstypes.WebhookCore{
- Identifier: "webhook",
- DisplayName: "webhook",
- URL: "http://example.com",
- Enabled: true,
- Insecure: false,
- Triggers: []gitnessenum.WebhookTrigger{gitnessenum.WebhookTriggerArtifactCreated},
- Created: createdAt,
- Updated: updatedAt,
- Description: description,
- SecretIdentifier: secretIdentifier,
- SecretSpaceID: 1,
- ExtraHeaders: extraHeaders,
- LatestExecutionResult: &latestExecutionResult,
- }
+ mockSpacePathStore.On("FindPrimaryBySpaceID", mock.Anything, int64(1)).Return(nil, fmt.Errorf("space not found"))
- mockSpacePathStore.On("FindPrimaryBySpaceID", ctx, int64(1)).Return(nil, fmt.Errorf("error finding primary by space ID"))
+ // WHEN
+ result, err := helper.MapToWebhookResponseEntity(context.Background(), webhook)
- webhookResponseEntity, err := helper.MapToWebhookResponseEntity(ctx, &createdWebhook)
+ // THEN
assert.Error(t, err)
- assert.Nil(t, webhookResponseEntity)
- assert.Contains(t, err.Error(), "failed to get secret space path: error finding primary by space ID")
+ assert.Nil(t, result)
+ mockSpacePathStore.AssertExpectations(t)
+}
+
+func TestGetRegistryRequestBaseInfo(t *testing.T) {
+ tests := []struct {
+ name string
+ parentRef string
+ registryName string
+ setupMocks func(*mocks.SpacePathStore, *mocks.SpaceFinder, *mocks.RegistryRepository)
+ expectedError string
+ validate func(*testing.T, *types.RegistryRequestBaseInfo, error)
+ }{
+ {
+ name: "success_case",
+ parentRef: "root/parent",
+ registryName: "reg",
+ setupMocks: func(_ *mocks.SpacePathStore, mockSpaceFinder *mocks.SpaceFinder, mockRegistryRepository *mocks.RegistryRepository) {
+ mockSpaceFinder.On("FindByRef", mock.Anything, "root").Return(&gitnesstypes.SpaceCore{ID: 1}, nil)
+ mockSpaceFinder.On("FindByRef", mock.Anything, "root/parent").Return(&gitnesstypes.SpaceCore{ID: 2}, nil)
+ mockRegistryRepository.On("GetByParentIDAndName", mock.Anything, int64(2), "reg").Return(&types.Registry{
+ ID: 3,
+ Type: api.RegistryTypeVIRTUAL,
+ }, nil)
+ },
+ validate: func(t *testing.T, baseInfo *types.RegistryRequestBaseInfo, err error) {
+ assert.NoError(t, err, "should not return error")
+ assert.NotNil(t, baseInfo, "baseInfo should not be nil")
+ assert.Equal(t, int64(1), baseInfo.RootIdentifierID, "root ID should match")
+ assert.Equal(t, int64(2), baseInfo.ParentID, "parent ID should match")
+ assert.Equal(t, int64(3), baseInfo.RegistryID, "registry ID should match")
+ assert.Equal(t, api.RegistryTypeVIRTUAL, baseInfo.RegistryType, "registry type should match")
+ },
+ },
+ {
+ name: "empty_parent_ref",
+ parentRef: "",
+ registryName: "reg",
+ expectedError: "parent reference is required",
+ },
+ {
+ name: "invalid_parent_ref",
+ parentRef: "/",
+ registryName: "reg",
+ expectedError: "invalid parent reference",
+ },
+ {
+ name: "root_space_not_found",
+ parentRef: "root/parent",
+ registryName: "reg",
+ setupMocks: func(_ *mocks.SpacePathStore, mockSpaceFinder *mocks.SpaceFinder, _ *mocks.RegistryRepository) {
+ mockSpaceFinder.On("FindByRef", mock.Anything, "root").Return(nil, fmt.Errorf("not found"))
+ },
+ expectedError: "root space not found",
+ },
+ {
+ name: "parent_space_not_found",
+ parentRef: "root/parent",
+ registryName: "reg",
+ setupMocks: func(_ *mocks.SpacePathStore, mockSpaceFinder *mocks.SpaceFinder, _ *mocks.RegistryRepository) {
+ mockSpaceFinder.On("FindByRef", mock.Anything, "root").Return(&gitnesstypes.SpaceCore{ID: 1}, nil)
+ mockSpaceFinder.On("FindByRef", mock.Anything, "root/parent").Return(nil, fmt.Errorf("not found"))
+ },
+ expectedError: "parent space not found",
+ },
+ {
+ name: "registry_not_found",
+ parentRef: "root/parent",
+ registryName: "reg",
+ setupMocks: func(_ *mocks.SpacePathStore, mockSpaceFinder *mocks.SpaceFinder, mockRegistryRepository *mocks.RegistryRepository) {
+ mockSpaceFinder.On("FindByRef", mock.Anything, "root").Return(&gitnesstypes.SpaceCore{ID: 1}, nil)
+ mockSpaceFinder.On("FindByRef", mock.Anything, "root/parent").Return(&gitnesstypes.SpaceCore{ID: 2}, nil)
+ mockRegistryRepository.On("GetByParentIDAndName", mock.Anything, int64(2), "reg").Return(nil, fmt.Errorf("not found"))
+ },
+ expectedError: "registry not found",
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ // Create mocks
+ mockSpacePathStore := new(mocks.SpacePathStore)
+ mockSpaceFinder := new(mocks.SpaceFinder)
+ mockRegistryRepository := new(mocks.RegistryRepository)
+
+ // Create helper
+ helper := &GitnessRegistryMetadataHelper{
+ spacePathStore: mockSpacePathStore,
+ spaceFinder: mockSpaceFinder,
+ registryRepository: mockRegistryRepository,
+ }
+
+ // Setup mocks if provided
+ if tt.setupMocks != nil {
+ tt.setupMocks(mockSpacePathStore, mockSpaceFinder, mockRegistryRepository)
+ }
+
+ // Execute test
+ baseInfo, err := helper.GetRegistryRequestBaseInfo(context.Background(), tt.parentRef, tt.registryName)
+
+ // Validate results
+ if tt.expectedError != "" {
+ assert.Error(t, err, "should return error")
+ assert.Contains(t, err.Error(), tt.expectedError, "error message should match")
+ assert.Nil(t, baseInfo, "baseInfo should be nil")
+ } else if tt.validate != nil {
+ tt.validate(t, baseInfo, err)
+ }
+
+ // Verify mock expectations
+ mockSpacePathStore.AssertExpectations(t)
+ mockSpaceFinder.AssertExpectations(t)
+ mockRegistryRepository.AssertExpectations(t)
+ })
+ }
}
func TestMapToInternalWebhookTriggers(t *testing.T) {
helper := &GitnessRegistryMetadataHelper{}
- apiTriggers := []api.Trigger{
- api.TriggerARTIFACTCREATION,
- api.TriggerARTIFACTDELETION,
+ tests := []struct {
+ name string
+ triggers []api.Trigger
+ expected []gitnessenum.WebhookTrigger
+ }{
+ {
+ name: "success_case",
+ triggers: []api.Trigger{
+ api.TriggerARTIFACTCREATION,
+ api.TriggerARTIFACTDELETION,
+ },
+ expected: []gitnessenum.WebhookTrigger{
+ gitnessenum.WebhookTriggerArtifactCreated,
+ gitnessenum.WebhookTriggerArtifactDeleted,
+ },
+ },
+ {
+ name: "empty_triggers",
+ triggers: []api.Trigger{},
+ expected: []gitnessenum.WebhookTrigger{},
+ },
}
- expectedInternalTriggers := []gitnessenum.WebhookTrigger{
- gitnessenum.WebhookTriggerArtifactCreated,
- gitnessenum.WebhookTriggerArtifactDeleted,
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ result := helper.MapToInternalWebhookTriggers(tt.triggers)
+ assert.Equal(t, tt.expected, result, "triggers should match")
+ })
}
-
- internalTriggers := helper.MapToInternalWebhookTriggers(apiTriggers)
- assert.Equal(t, expectedInternalTriggers, internalTriggers)
}
func TestMapToAPIWebhookTriggers(t *testing.T) {
helper := &GitnessRegistryMetadataHelper{}
- internalTriggers := []gitnessenum.WebhookTrigger{
- gitnessenum.WebhookTriggerArtifactCreated,
- gitnessenum.WebhookTriggerArtifactDeleted,
+ tests := []struct {
+ name string
+ triggers []gitnessenum.WebhookTrigger
+ expected []api.Trigger
+ }{
+ {
+ name: "success_case",
+ triggers: []gitnessenum.WebhookTrigger{
+ gitnessenum.WebhookTriggerArtifactCreated,
+ gitnessenum.WebhookTriggerArtifactDeleted,
+ },
+ expected: []api.Trigger{
+ api.TriggerARTIFACTCREATION,
+ api.TriggerARTIFACTDELETION,
+ },
+ },
+ {
+ name: "empty_triggers",
+ triggers: []gitnessenum.WebhookTrigger{},
+ expected: []api.Trigger{},
+ },
}
- expectedAPITriggers := []api.Trigger{
- api.TriggerARTIFACTCREATION,
- api.TriggerARTIFACTDELETION,
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ result := helper.MapToAPIWebhookTriggers(tt.triggers)
+ assert.Equal(t, tt.expected, result, "triggers should match")
+ })
}
-
- apiTriggers := helper.MapToAPIWebhookTriggers(internalTriggers)
- assert.Equal(t, expectedAPITriggers, apiTriggers)
}
diff --git a/registry/app/api/controller/metadata/retrigger_webhook_execution_test.go b/registry/app/api/controller/metadata/retrigger_webhook_execution_test.go
index 4c4fcfcca..4c8e5640c 100644
--- a/registry/app/api/controller/metadata/retrigger_webhook_execution_test.go
+++ b/registry/app/api/controller/metadata/retrigger_webhook_execution_test.go
@@ -12,7 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package metadata
+//nolint:lll
+package metadata_test
import (
"context"
@@ -21,256 +22,302 @@ import (
"time"
gitnesswebhook "github.com/harness/gitness/app/services/webhook"
+ "github.com/harness/gitness/registry/app/api/controller/metadata"
+ "github.com/harness/gitness/registry/app/api/controller/mocks"
api "github.com/harness/gitness/registry/app/api/openapi/contracts/artifact"
- gitnesstypes "github.com/harness/gitness/types"
+ "github.com/harness/gitness/registry/types"
+ coretypes "github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
-//nolint:lll
-func TestReTriggerWebhookExecution_Success(t *testing.T) {
- ctx := context.Background()
- mockSpaceFinder := new(MockSpaceFinder)
- mockRegistryRepository := new(MockRegistryRepository)
- mockWebhooksRepository := new(MockWebhooksRepository)
- mockWebhooksExecutionRepository := new(MockWebhooksExecutionRepository)
- mockAuthorizer := new(MockAuthorizer)
- mockRegistryMetadataHelper := new(MockRegistryMetadataHelper)
- mockMockWebhookService := new(MockWebhookService)
- controller := &APIController{
- SpaceFinder: mockSpaceFinder,
- RegistryRepository: mockRegistryRepository,
- WebhooksRepository: mockWebhooksRepository,
- WebhooksExecutionRepository: mockWebhooksExecutionRepository,
- Authorizer: mockAuthorizer,
- RegistryMetadataHelper: mockRegistryMetadataHelper,
- WebhookService: mockMockWebhookService,
- }
-
- regInfo := &RegistryRequestBaseInfo{
- RegistryID: 1,
- RegistryIdentifier: "reg",
- ParentRef: "root/parent",
- }
- space := &gitnesstypes.SpaceCore{ID: 2}
- var permissionChecks []gitnesstypes.PermissionCheck
- mockRegistryMetadataHelper.On("GetRegistryRequestBaseInfo", ctx, "", "reg").Return(regInfo, nil)
- mockSpaceFinder.On("FindByRef", ctx, "root/parent").Return(space, nil)
- mockRegistryMetadataHelper.On("GetPermissionChecks", space, regInfo.RegistryIdentifier, enum.PermissionRegistryEdit).Return(permissionChecks)
- mockAuthorizer.On("CheckAll", ctx, mock.Anything, permissionChecks).Return(true, nil)
- latestExecutionResult := enum.WebhookExecutionResultSuccess
- mockMockWebhookService.On("ReTriggerWebhookExecution", ctx, int64(1)).Return(&gitnesswebhook.TriggerResult{
- Execution: &gitnesstypes.WebhookExecutionCore{
- ID: 1,
- Created: time.Now().Unix(),
- Duration: 100,
- Error: "none",
- Request: gitnesstypes.WebhookExecutionRequest{Body: "{}", Headers: "headers", URL: "http://example.com"},
- Response: gitnesstypes.WebhookExecutionResponse{Body: "{}", Headers: "headers", Status: "200 OK", StatusCode: 200},
- RetriggerOf: nil,
- Retriggerable: true,
- WebhookID: 4,
- Result: enum.WebhookExecutionResultSuccess,
- TriggerType: enum.WebhookTriggerArtifactCreated},
- Webhook: &gitnesstypes.WebhookCore{
- Identifier: "webhook",
- DisplayName: "webhook",
- URL: "http://example.com",
- Enabled: true,
- Insecure: false,
- Triggers: []enum.WebhookTrigger{enum.WebhookTriggerArtifactCreated},
- Created: time.Now().Unix(),
- Updated: time.Now().Unix(),
- Description: "Test webhook",
- SecretSpaceID: 1,
- ExtraHeaders: []gitnesstypes.ExtraHeader{{Key: "key", Value: "value"}},
- LatestExecutionResult: &latestExecutionResult,
+var (
+ webhookExecution = &coretypes.WebhookExecutionCore{
+ ID: 1,
+ Created: time.Now().Unix(),
+ WebhookID: 1,
+ Result: enum.WebhookExecutionResultSuccess,
+ Duration: 100,
+ Error: "",
+ Retriggerable: false,
+ Request: coretypes.WebhookExecutionRequest{
+ URL: "http://example.com",
+ Headers: "{}",
+ Body: "{}",
+ },
+ Response: coretypes.WebhookExecutionResponse{
+ StatusCode: 200,
+ Status: "OK",
+ Headers: "{}",
+ Body: "{}",
},
TriggerType: enum.WebhookTriggerArtifactCreated,
- }, nil)
-
- r := api.ReTriggerWebhookExecutionRequestObject{
- RegistryRef: "reg",
- WebhookIdentifier: "webhook",
- WebhookExecutionId: "1",
}
- response, err := controller.ReTriggerWebhookExecution(ctx, r)
- reTriggerWebhookExecution200JSONResponse, ok := response.(api.ReTriggerWebhookExecution200JSONResponse)
- if !ok {
- t.Fatalf("expected api.ReTriggerWebhookExecution200JSONResponse, got %T", response)
+ webhookExecutionEntity = &api.WebhookExecution{
+ Id: &webhookExecution.ID,
+ Created: &webhookExecution.Created,
+ Duration: &webhookExecution.Duration,
+ RetriggerOf: webhookExecution.RetriggerOf,
+ Retriggerable: &webhookExecution.Retriggerable,
+ Error: &webhookExecution.Error,
+ WebhookId: &webhookExecution.WebhookID,
+ Request: &api.WebhookExecRequest{
+ Body: &webhookExecution.Request.Body,
+ Headers: &webhookExecution.Request.Headers,
+ Url: &webhookExecution.Request.URL,
+ },
+ Response: &api.WebhookExecResponse{
+ Status: &webhookExecution.Response.Status,
+ StatusCode: &webhookExecution.Response.StatusCode,
+ Body: &webhookExecution.Response.Body,
+ Headers: &webhookExecution.Response.Headers,
+ },
+ Result: &[]api.WebhookExecResult{api.WebhookExecResultSUCCESS}[0],
+ TriggerType: &[]api.Trigger{api.TriggerARTIFACTCREATION}[0],
+ }
+)
+
+func TestReTriggerWebhookExecution(t *testing.T) {
+ // Create mocks that will be used across all tests
+ mockSpaceFinder := new(mocks.SpaceFinder)
+ mockRegistryRepository := new(mocks.RegistryRepository)
+ mockWebhooksRepository := new(mocks.WebhooksRepository)
+ mockWebhooksExecutionRepository := new(mocks.WebhooksExecutionRepository)
+ mockAuthorizer := new(mocks.Authorizer)
+ mockRegistryMetadataHelper := new(mocks.RegistryMetadataHelper)
+ mockWebhookService := new(mocks.WebhookService)
+
+ tests := []struct {
+ name string
+ setupMocks func(*metadata.APIController)
+ request api.ReTriggerWebhookExecutionRequestObject
+ expectedResp api.ReTriggerWebhookExecutionResponseObject
+ expectedError error
+ }{
+ {
+ name: "success_case",
+ setupMocks: func(_ *metadata.APIController) {
+ regInfo := &types.RegistryRequestBaseInfo{
+ RegistryID: 1,
+ RegistryIdentifier: "reg",
+ ParentRef: "root/parent",
+ }
+ space := &coretypes.SpaceCore{ID: 2}
+ var permissionChecks []coretypes.PermissionCheck
+
+ mockRegistryMetadataHelper.On("GetRegistryRequestBaseInfo", mock.Anything, "", "reg").Return(regInfo, nil)
+ mockSpaceFinder.On("FindByRef", mock.Anything, "root/parent").Return(space, nil)
+ mockRegistryMetadataHelper.On("GetPermissionChecks", space, regInfo.RegistryIdentifier, enum.PermissionRegistryEdit).Return(permissionChecks)
+ mockAuthorizer.On("CheckAll", mock.Anything, mock.Anything, mock.Anything).Return(true, nil)
+
+ latestExecutionResult := enum.WebhookExecutionResultSuccess
+ mockWebhookService.On("ReTriggerWebhookExecution", mock.Anything, int64(1)).Return(&gitnesswebhook.TriggerResult{
+ Execution: webhookExecution,
+ Webhook: &coretypes.WebhookCore{
+ Identifier: "webhook",
+ DisplayName: "webhook",
+ URL: "http://example.com",
+ Enabled: true,
+ Insecure: false,
+ Triggers: []enum.WebhookTrigger{enum.WebhookTriggerArtifactCreated},
+ Created: webhookExecution.Created,
+ Updated: webhookExecution.Created,
+ Description: "Test webhook",
+ SecretSpaceID: 1,
+ ExtraHeaders: []coretypes.ExtraHeader{{Key: "key", Value: "value"}},
+ LatestExecutionResult: &latestExecutionResult,
+ },
+ TriggerType: enum.WebhookTriggerArtifactCreated,
+ }, nil)
+ },
+ request: api.ReTriggerWebhookExecutionRequestObject{
+ WebhookIdentifier: "webhook",
+ RegistryRef: "reg",
+ WebhookExecutionId: "1",
+ },
+ expectedResp: api.ReTriggerWebhookExecution200JSONResponse{
+ WebhookExecutionResponseJSONResponse: api.WebhookExecutionResponseJSONResponse{
+ Data: *webhookExecutionEntity,
+ Status: api.StatusSUCCESS,
+ },
+ },
+ },
+ {
+ name: "permission_check_fails",
+ setupMocks: func(_ *metadata.APIController) {
+ regInfo := &types.RegistryRequestBaseInfo{
+ RegistryID: 1,
+ RegistryIdentifier: "reg",
+ ParentRef: "root/parent",
+ }
+ space := &coretypes.SpaceCore{ID: 2}
+ var permissionChecks []coretypes.PermissionCheck
+
+ mockRegistryMetadataHelper.On("GetRegistryRequestBaseInfo", mock.Anything, "", "reg").Return(regInfo, nil)
+ mockSpaceFinder.On("FindByRef", mock.Anything, "root/parent").Return(space, nil)
+ mockRegistryMetadataHelper.On("GetPermissionChecks", space, regInfo.RegistryIdentifier, enum.PermissionRegistryEdit).Return(permissionChecks)
+ mockAuthorizer.On("CheckAll", mock.Anything, mock.Anything, mock.Anything).Return(false, nil)
+ },
+ request: api.ReTriggerWebhookExecutionRequestObject{
+ WebhookIdentifier: "webhook",
+ RegistryRef: "reg",
+ WebhookExecutionId: "1",
+ },
+ expectedResp: api.ReTriggerWebhookExecution403JSONResponse{
+ UnauthorizedJSONResponse: api.UnauthorizedJSONResponse{
+ Code: "403",
+ Message: "not authorized",
+ },
+ },
+ },
+ {
+ name: "invalid_execution_identifier",
+ setupMocks: func(_ *metadata.APIController) {
+ regInfo := &types.RegistryRequestBaseInfo{
+ RegistryID: 1,
+ RegistryIdentifier: "reg",
+ ParentRef: "root/parent",
+ }
+ space := &coretypes.SpaceCore{ID: 2}
+ var permissionChecks []coretypes.PermissionCheck
+
+ mockRegistryMetadataHelper.On("GetRegistryRequestBaseInfo", mock.Anything, "", "reg").Return(regInfo, nil)
+ mockSpaceFinder.On("FindByRef", mock.Anything, "root/parent").Return(space, nil)
+ mockRegistryMetadataHelper.On("GetPermissionChecks", space, regInfo.RegistryIdentifier, enum.PermissionRegistryEdit).Return(permissionChecks)
+ mockAuthorizer.On("CheckAll", mock.Anything, mock.Anything, mock.Anything).Return(true, nil)
+ },
+ request: api.ReTriggerWebhookExecutionRequestObject{
+ WebhookIdentifier: "webhook",
+ RegistryRef: "reg",
+ WebhookExecutionId: "invalid",
+ },
+ expectedResp: api.ReTriggerWebhookExecution400JSONResponse{
+ BadRequestJSONResponse: api.BadRequestJSONResponse{
+ Code: "400",
+ Message: "invalid webhook execution identifier: invalid, err: strconv.ParseInt: parsing \"invalid\": invalid syntax",
+ },
+ },
+ },
+ {
+ name: "retrigger_execution_error",
+ setupMocks: func(_ *metadata.APIController) {
+ regInfo := &types.RegistryRequestBaseInfo{
+ RegistryID: 1,
+ RegistryIdentifier: "reg",
+ ParentRef: "root/parent",
+ }
+ space := &coretypes.SpaceCore{ID: 2}
+ var permissionChecks []coretypes.PermissionCheck
+
+ mockRegistryMetadataHelper.On("GetRegistryRequestBaseInfo", mock.Anything, "", "reg").Return(regInfo, nil)
+ mockSpaceFinder.On("FindByRef", mock.Anything, "root/parent").Return(space, nil)
+ mockRegistryMetadataHelper.On("GetPermissionChecks", space, regInfo.RegistryIdentifier, enum.PermissionRegistryEdit).Return(permissionChecks)
+ mockAuthorizer.On("CheckAll", mock.Anything, mock.Anything, mock.Anything).Return(true, nil)
+ mockWebhookService.On("ReTriggerWebhookExecution", mock.Anything, int64(1)).Return(nil, fmt.Errorf("error"))
+ },
+ request: api.ReTriggerWebhookExecutionRequestObject{
+ WebhookIdentifier: "webhook",
+ RegistryRef: "reg",
+ WebhookExecutionId: "1",
+ },
+ expectedResp: api.ReTriggerWebhookExecution500JSONResponse{
+ InternalServerErrorJSONResponse: api.InternalServerErrorJSONResponse{
+ Code: "500",
+ Message: "failed to re-trigger execution: error",
+ },
+ },
+ },
}
- assert.NoError(t, err)
- assert.NotNil(t, response)
- assert.Equal(t, api.StatusSUCCESS, reTriggerWebhookExecution200JSONResponse.Status)
- assert.Equal(t, int64(1), *reTriggerWebhookExecution200JSONResponse.Data.Id)
- assert.Equal(t, "none", *reTriggerWebhookExecution200JSONResponse.Data.Error)
- assert.Equal(t, "{}", *reTriggerWebhookExecution200JSONResponse.Data.Request.Body)
- assert.Equal(t, "headers", *reTriggerWebhookExecution200JSONResponse.Data.Request.Headers)
- assert.Equal(t, "http://example.com", *reTriggerWebhookExecution200JSONResponse.Data.Request.Url)
- assert.Equal(t, "{}", *reTriggerWebhookExecution200JSONResponse.Data.Response.Body)
- assert.Equal(t, "headers", *reTriggerWebhookExecution200JSONResponse.Data.Response.Headers)
- assert.Equal(t, "200 OK", *reTriggerWebhookExecution200JSONResponse.Data.Response.Status)
- assert.Equal(t, 200, *reTriggerWebhookExecution200JSONResponse.Data.Response.StatusCode)
- assert.Equal(t, api.WebhookExecResultSUCCESS, *reTriggerWebhookExecution200JSONResponse.Data.Result)
- assert.Equal(t, api.TriggerARTIFACTCREATION, *reTriggerWebhookExecution200JSONResponse.Data.TriggerType)
- assert.Equal(t, api.StatusSUCCESS, reTriggerWebhookExecution200JSONResponse.Status)
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ // Clear mock expectations
+ mockSpaceFinder.ExpectedCalls = nil
+ mockRegistryRepository.ExpectedCalls = nil
+ mockWebhooksRepository.ExpectedCalls = nil
+ mockWebhooksExecutionRepository.ExpectedCalls = nil
+ mockAuthorizer.ExpectedCalls = nil
+ mockRegistryMetadataHelper.ExpectedCalls = nil
+ mockWebhookService.ExpectedCalls = nil
- mockRegistryMetadataHelper.AssertExpectations(t)
- mockSpaceFinder.AssertExpectations(t)
- mockAuthorizer.AssertExpectations(t)
- mockWebhooksExecutionRepository.AssertExpectations(t)
- mockMockWebhookService.AssertExpectations(t)
-}
-
-//nolint:lll
-func TestReTriggerWebhookExecution_PermissionCheckFails(t *testing.T) {
- ctx := context.Background()
- mockSpaceFinder := new(MockSpaceFinder)
- mockRegistryRepository := new(MockRegistryRepository)
- mockWebhooksRepository := new(MockWebhooksRepository)
- mockWebhooksExecutionRepository := new(MockWebhooksExecutionRepository)
- mockAuthorizer := new(MockAuthorizer)
- mockRegistryMetadataHelper := new(MockRegistryMetadataHelper)
- mockMockWebhookService := new(MockWebhookService)
- controller := &APIController{
- SpaceFinder: mockSpaceFinder,
- RegistryRepository: mockRegistryRepository,
- WebhooksRepository: mockWebhooksRepository,
- WebhooksExecutionRepository: mockWebhooksExecutionRepository,
- Authorizer: mockAuthorizer,
- RegistryMetadataHelper: mockRegistryMetadataHelper,
- WebhookService: mockMockWebhookService,
- }
-
- regInfo := &RegistryRequestBaseInfo{
- RegistryID: 1,
- RegistryIdentifier: "reg",
- ParentRef: "root/parent",
- }
- space := &gitnesstypes.SpaceCore{ID: 2}
- var permissionChecks []gitnesstypes.PermissionCheck
- mockRegistryMetadataHelper.On("GetRegistryRequestBaseInfo", ctx, "", "reg").Return(regInfo, nil)
- mockSpaceFinder.On("FindByRef", ctx, "root/parent").Return(space, nil)
- mockRegistryMetadataHelper.On("GetPermissionChecks", space, regInfo.RegistryIdentifier, enum.PermissionRegistryEdit).Return(permissionChecks)
- mockAuthorizer.On("CheckAll", ctx, mock.Anything, permissionChecks).Return(false, nil)
-
- r := api.ReTriggerWebhookExecutionRequestObject{
- RegistryRef: "reg",
- WebhookIdentifier: "webhook",
- WebhookExecutionId: "1",
- }
-
- response, err := controller.ReTriggerWebhookExecution(ctx, r)
- assert.NoError(t, err)
- assert.NotNil(t, response)
- assert.IsType(t, api.ReTriggerWebhookExecution403JSONResponse{}, response)
- assert.Equal(t, "forbidden", response.(api.ReTriggerWebhookExecution403JSONResponse).Message) //nolint:errcheck
-
- mockRegistryMetadataHelper.AssertExpectations(t)
- mockSpaceFinder.AssertExpectations(t)
- mockAuthorizer.AssertExpectations(t)
-}
-
-//nolint:lll
-func TestReTriggerWebhookExecution_InvalidExecutionIdentifier(t *testing.T) {
- ctx := context.Background()
- mockSpaceFinder := new(MockSpaceFinder)
- mockRegistryRepository := new(MockRegistryRepository)
- mockWebhooksRepository := new(MockWebhooksRepository)
- mockWebhooksExecutionRepository := new(MockWebhooksExecutionRepository)
- mockAuthorizer := new(MockAuthorizer)
- mockRegistryMetadataHelper := new(MockRegistryMetadataHelper)
- mockMockWebhookService := new(MockWebhookService)
- controller := &APIController{
- SpaceFinder: mockSpaceFinder,
- RegistryRepository: mockRegistryRepository,
- WebhooksRepository: mockWebhooksRepository,
- WebhooksExecutionRepository: mockWebhooksExecutionRepository,
- Authorizer: mockAuthorizer,
- RegistryMetadataHelper: mockRegistryMetadataHelper,
- WebhookService: mockMockWebhookService,
- }
-
- regInfo := &RegistryRequestBaseInfo{
- RegistryID: 1,
- RegistryIdentifier: "reg",
- ParentRef: "root/parent",
- }
- space := &gitnesstypes.SpaceCore{ID: 2}
- var permissionChecks []gitnesstypes.PermissionCheck
- mockRegistryMetadataHelper.On("GetRegistryRequestBaseInfo", ctx, "", "reg").Return(regInfo, nil)
- mockSpaceFinder.On("FindByRef", ctx, "root/parent").Return(space, nil)
- mockRegistryMetadataHelper.On("GetPermissionChecks", space, regInfo.RegistryIdentifier, enum.PermissionRegistryEdit).Return(permissionChecks)
- mockAuthorizer.On("CheckAll", ctx, mock.Anything, permissionChecks).Return(true, nil)
-
- r := api.ReTriggerWebhookExecutionRequestObject{
- RegistryRef: "reg",
- WebhookIdentifier: "webhook",
- WebhookExecutionId: "invalid",
- }
-
- response, err := controller.ReTriggerWebhookExecution(ctx, r)
- assert.NoError(t, err)
- assert.NotNil(t, response)
- assert.IsType(t, api.ReTriggerWebhookExecution400JSONResponse{}, response)
- assert.Equal(t, "invalid webhook execution identifier: invalid, err: strconv.ParseInt: parsing \"invalid\": invalid syntax",
- response.(api.ReTriggerWebhookExecution400JSONResponse).Message) //nolint:errcheck
-
- mockRegistryMetadataHelper.AssertExpectations(t)
- mockSpaceFinder.AssertExpectations(t)
- mockAuthorizer.AssertExpectations(t)
-}
-
-//nolint:lll
-func TestReTriggerWebhookExecution_ReTriggerExecutionError(t *testing.T) {
- ctx := context.Background()
- mockSpaceFinder := new(MockSpaceFinder)
- mockRegistryRepository := new(MockRegistryRepository)
- mockWebhooksRepository := new(MockWebhooksRepository)
- mockWebhooksExecutionRepository := new(MockWebhooksExecutionRepository)
- mockAuthorizer := new(MockAuthorizer)
- mockRegistryMetadataHelper := new(MockRegistryMetadataHelper)
- mockMockWebhookService := new(MockWebhookService)
- controller := &APIController{
- SpaceFinder: mockSpaceFinder,
- RegistryRepository: mockRegistryRepository,
- WebhooksRepository: mockWebhooksRepository,
- WebhooksExecutionRepository: mockWebhooksExecutionRepository,
- Authorizer: mockAuthorizer,
- RegistryMetadataHelper: mockRegistryMetadataHelper,
- WebhookService: mockMockWebhookService,
- }
-
- regInfo := &RegistryRequestBaseInfo{
- RegistryID: 1,
- RegistryIdentifier: "reg",
- ParentRef: "root/parent",
- }
- space := &gitnesstypes.SpaceCore{ID: 2}
- var permissionChecks []gitnesstypes.PermissionCheck
- mockRegistryMetadataHelper.On("GetRegistryRequestBaseInfo", ctx, "", "reg").Return(regInfo, nil)
- mockSpaceFinder.On("FindByRef", ctx, "root/parent").Return(space, nil)
- mockRegistryMetadataHelper.On("GetPermissionChecks", space, regInfo.RegistryIdentifier, enum.PermissionRegistryEdit).Return(permissionChecks)
- mockAuthorizer.On("CheckAll", ctx, mock.Anything, permissionChecks).Return(true, nil)
- mockMockWebhookService.On("ReTriggerWebhookExecution", ctx, int64(1)).Return(nil, fmt.Errorf("error"))
-
- r := api.ReTriggerWebhookExecutionRequestObject{
- RegistryRef: "reg",
- WebhookIdentifier: "webhook",
- WebhookExecutionId: "1",
- }
-
- response, err := controller.ReTriggerWebhookExecution(ctx, r)
- assert.NoError(t, err)
- assert.NotNil(t, response)
- assert.IsType(t, api.ReTriggerWebhookExecution500JSONResponse{}, response)
- assert.Equal(t, "failed to re-trigger execution: error", response.(api.ReTriggerWebhookExecution500JSONResponse).Message) //nolint:errcheck
-
- mockRegistryMetadataHelper.AssertExpectations(t)
- mockSpaceFinder.AssertExpectations(t)
- mockAuthorizer.AssertExpectations(t)
+ controller := &metadata.APIController{
+ SpaceFinder: mockSpaceFinder,
+ RegistryRepository: mockRegistryRepository,
+ WebhooksRepository: mockWebhooksRepository,
+ WebhooksExecutionRepository: mockWebhooksExecutionRepository,
+ Authorizer: mockAuthorizer,
+ RegistryMetadataHelper: mockRegistryMetadataHelper,
+ WebhookService: mockWebhookService,
+ }
+
+ // Setup mocks
+ tt.setupMocks(controller)
+
+ resp, err := controller.ReTriggerWebhookExecution(context.Background(), tt.request)
+ assert.Equal(t, tt.expectedError, err)
+ assert.NotNil(t, resp, "response should not be nil")
+
+ switch tt.name {
+ case "success_case":
+ successResp, ok := resp.(api.ReTriggerWebhookExecution200JSONResponse)
+ assert.True(t, ok, "expected 200 response")
+ assert.Equal(t, api.StatusSUCCESS, successResp.Status)
+ assert.NotNil(t, successResp.Data, "Data should not be nil")
+ assert.NotNil(t, successResp.Data.Id, "Id should not be nil")
+ assert.NotNil(t, successResp.Data.Error, "Error should not be nil")
+ assert.NotNil(t, successResp.Data.Request, "Request should not be nil")
+ assert.NotNil(t, successResp.Data.Response, "Response should not be nil")
+ assert.NotNil(t, successResp.Data.Result, "Result should not be nil")
+ assert.NotNil(t, successResp.Data.TriggerType, "TriggerType should not be nil")
+
+ if assert.NotNil(t, successResp.Data.Request) {
+ assert.Equal(t, "{}", *successResp.Data.Request.Body)
+ assert.Equal(t, "{}", *successResp.Data.Request.Headers)
+ assert.Equal(t, "http://example.com", *successResp.Data.Request.Url)
+ }
+
+ if assert.NotNil(t, successResp.Data.Response) {
+ assert.Equal(t, "{}", *successResp.Data.Response.Body)
+ assert.Equal(t, "{}", *successResp.Data.Response.Headers)
+ assert.Equal(t, "OK", *successResp.Data.Response.Status)
+ assert.Equal(t, 200, *successResp.Data.Response.StatusCode)
+ }
+
+ assert.Equal(t, int64(1), *successResp.Data.Id)
+ assert.Equal(t, "", *successResp.Data.Error)
+ assert.Equal(t, api.WebhookExecResultSUCCESS, *successResp.Data.Result)
+ assert.Equal(t, api.TriggerARTIFACTCREATION, *successResp.Data.TriggerType)
+
+ case "permission_check_fails":
+ assert.IsType(t, api.ReTriggerWebhookExecution403JSONResponse{}, resp, "expected 403 response")
+ errorResp, _ := resp.(api.ReTriggerWebhookExecution403JSONResponse) //nolint:errcheck
+ assert.Equal(t, "403", errorResp.Code)
+ assert.Equal(t, "forbidden", errorResp.Message)
+
+ case "invalid_execution_identifier":
+ assert.IsType(t, api.ReTriggerWebhookExecution400JSONResponse{}, resp, "expected 400 response")
+ errorResp, _ := resp.(api.ReTriggerWebhookExecution400JSONResponse) //nolint:errcheck
+ assert.Equal(t, "400", errorResp.Code)
+ assert.Equal(t, "invalid webhook execution identifier: invalid, err: strconv.ParseInt: parsing \"invalid\": invalid syntax", errorResp.Message)
+
+ case "retrigger_execution_error":
+ assert.IsType(t, api.ReTriggerWebhookExecution500JSONResponse{}, resp, "expected 500 response")
+ errorResp, _ := resp.(api.ReTriggerWebhookExecution500JSONResponse) //nolint:errcheck
+ assert.Equal(t, "500", errorResp.Code)
+ assert.Equal(t, "failed to re-trigger execution: error", errorResp.Message)
+ }
+
+ // Verify all mock expectations
+ mockSpaceFinder.AssertExpectations(t)
+ mockRegistryRepository.AssertExpectations(t)
+ mockWebhooksRepository.AssertExpectations(t)
+ mockWebhooksExecutionRepository.AssertExpectations(t)
+ mockAuthorizer.AssertExpectations(t)
+ mockRegistryMetadataHelper.AssertExpectations(t)
+ mockWebhookService.AssertExpectations(t)
+ })
+ }
}
diff --git a/registry/app/api/controller/metadata/update_artifact.go b/registry/app/api/controller/metadata/update_artifact.go
index ce220b6b2..40bdf4948 100644
--- a/registry/app/api/controller/metadata/update_artifact.go
+++ b/registry/app/api/controller/metadata/update_artifact.go
@@ -71,7 +71,7 @@ func (c *APIController) UpdateArtifactLabels(
a := string(r.Artifact)
- artifactEntity, err := c.ImageStore.GetByRepoAndName(ctx, regInfo.parentID, regInfo.RegistryIdentifier, a)
+ artifactEntity, err := c.ImageStore.GetByRepoAndName(ctx, regInfo.ParentID, regInfo.RegistryIdentifier, a)
if len(artifactEntity.Name) == 0 {
return artifact.UpdateArtifactLabels404JSONResponse{
@@ -95,7 +95,7 @@ func (c *APIController) UpdateArtifactLabels(
}
// TODO: use the correct way to get download count if this endpoint is used
- tag, err := c.TagStore.GetLatestTagMetadata(ctx, regInfo.parentID, regInfo.RegistryIdentifier, a)
+ tag, err := c.TagStore.GetLatestTagMetadata(ctx, regInfo.ParentID, regInfo.RegistryIdentifier, a)
if err != nil {
return artifact.UpdateArtifactLabels500JSONResponse{
diff --git a/registry/app/api/controller/metadata/update_registry.go b/registry/app/api/controller/metadata/update_registry.go
index 1fa25557d..693d18784 100644
--- a/registry/app/api/controller/metadata/update_registry.go
+++ b/registry/app/api/controller/metadata/update_registry.go
@@ -68,7 +68,7 @@ func (c *APIController) ModifyRegistry(
}, err
}
- repoEntity, err := c.RegistryRepository.GetByParentIDAndName(ctx, regInfo.parentID, regInfo.RegistryIdentifier)
+ repoEntity, err := c.RegistryRepository.GetByParentIDAndName(ctx, regInfo.ParentID, regInfo.RegistryIdentifier)
if err != nil {
return throwModifyRegistry500Error(err), err
}
@@ -77,7 +77,7 @@ func (c *APIController) ModifyRegistry(
return c.updateVirtualRegistry(ctx, r, repoEntity, err, regInfo, session)
}
upstreamproxyEntity, err := c.UpstreamProxyStore.GetByRegistryIdentifier(
- ctx, regInfo.parentID,
+ ctx, regInfo.ParentID,
regInfo.RegistryIdentifier,
)
if len(upstreamproxyEntity.RepoKey) == 0 {
@@ -93,7 +93,7 @@ func (c *APIController) ModifyRegistry(
registry, upstreamproxy, err := c.UpdateUpstreamProxyEntity(
ctx,
artifact.RegistryRequest(*r.Body),
- regInfo.parentID, regInfo.rootIdentifierID, upstreamproxyEntity,
+ regInfo.ParentID, regInfo.RootIdentifierID, upstreamproxyEntity,
)
registry.ID = repoEntity.ID
upstreamproxy.ID = upstreamproxyEntity.ID
@@ -133,7 +133,7 @@ func (c *APIController) ModifyRegistry(
func (c *APIController) updateVirtualRegistry(
ctx context.Context, r artifact.ModifyRegistryRequestObject, repoEntity *types.Registry, err error,
- regInfo *RegistryRequestBaseInfo, session *auth.Session,
+ regInfo *types.RegistryRequestBaseInfo, session *auth.Session,
) (artifact.ModifyRegistryResponseObject, error) {
if len(repoEntity.Name) == 0 {
return artifact.ModifyRegistry404JSONResponse{
@@ -158,7 +158,7 @@ func (c *APIController) updateVirtualRegistry(
),
}, nil
}
- err = c.setUpstreamProxyIDs(ctx, registry, artifact.RegistryRequest(*r.Body), regInfo.parentID)
+ err = c.setUpstreamProxyIDs(ctx, registry, artifact.RegistryRequest(*r.Body), regInfo.ParentID)
if err != nil {
return throwModifyRegistry500Error(err), nil
}
@@ -393,7 +393,7 @@ func (c *APIController) UpdateUpstreamProxyEntity(
}
if res.SecretSpacePath != nil && len(*res.SecretSpacePath) > 0 {
- upstreamProxyConfigEntity.SecretSpaceID, err = c.RegistryMetadataHelper.getSecretSpaceID(ctx, res.SecretSpacePath)
+ upstreamProxyConfigEntity.SecretSpaceID, err = c.RegistryMetadataHelper.GetSecretSpaceID(ctx, res.SecretSpacePath)
if err != nil {
return nil, nil, err
}
@@ -414,7 +414,7 @@ func (c *APIController) UpdateUpstreamProxyEntity(
default:
if res.AccessKeySecretSpacePath != nil && len(*res.AccessKeySecretSpacePath) > 0 {
upstreamProxyConfigEntity.UserNameSecretSpaceID, err =
- c.RegistryMetadataHelper.getSecretSpaceID(ctx, res.AccessKeySecretSpacePath)
+ c.RegistryMetadataHelper.GetSecretSpaceID(ctx, res.AccessKeySecretSpacePath)
if err != nil {
return nil, nil, err
}
@@ -426,7 +426,7 @@ func (c *APIController) UpdateUpstreamProxyEntity(
if res.SecretKeySpacePath != nil && len(*res.SecretKeySpacePath) > 0 {
upstreamProxyConfigEntity.SecretSpaceID, err =
- c.RegistryMetadataHelper.getSecretSpaceID(ctx, res.SecretKeySpacePath)
+ c.RegistryMetadataHelper.GetSecretSpaceID(ctx, res.SecretKeySpacePath)
if err != nil {
return nil, nil, err
}
diff --git a/registry/app/api/controller/metadata/utils_test.go b/registry/app/api/controller/metadata/utils_test.go
index 2180bc352..070497516 100644
--- a/registry/app/api/controller/metadata/utils_test.go
+++ b/registry/app/api/controller/metadata/utils_test.go
@@ -12,151 +12,545 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package metadata
+package metadata_test
import (
"testing"
"time"
+ "github.com/harness/gitness/registry/app/api/controller/metadata"
"github.com/harness/gitness/registry/app/api/openapi/contracts/artifact"
"github.com/stretchr/testify/assert"
)
-func TestValidatePackageTypes_ValidTypes(t *testing.T) {
- err := ValidatePackageTypes([]string{"DOCKER", "HELM"})
- assert.NoError(t, err)
-}
-
-func TestValidatePackageTypes_InvalidTypes(t *testing.T) {
- err := ValidatePackageTypes([]string{"INVALID"})
- assert.Error(t, err)
- assert.Equal(t, "invalid package type", err.Error())
-}
-
-func TestValidatePackageType_ValidType(t *testing.T) {
- err := ValidatePackageType("DOCKER")
- assert.NoError(t, err)
-}
-
-func TestValidatePackageType_InvalidType(t *testing.T) {
- err := ValidatePackageType("INVALID")
- assert.Error(t, err)
- assert.Equal(t, "invalid package type", err.Error())
-}
-
-func TestValidateIdentifier_ValidIdentifier(t *testing.T) {
- err := ValidateIdentifier("valid-identifier")
- assert.NoError(t, err)
-}
-
-func TestValidateIdentifier_InvalidIdentifier(t *testing.T) {
- err := ValidateIdentifier("Invalid Identifier")
- assert.Error(t, err)
- assert.Equal(t, RegistryIdentifierErrorMsg, err.Error())
-}
-
-func TestCleanURLPath_ValidURL(t *testing.T) {
- input := "https://example.com/path/"
- expected := "https://example.com/path"
- CleanURLPath(&input)
- assert.Equal(t, expected, input)
-}
-
-func TestCleanURLPath_InvalidURL(t *testing.T) {
- input := "://invalid-url"
- expected := "://invalid-url"
- CleanURLPath(&input)
- assert.Equal(t, expected, input)
-}
-
-func TestGetTimeInMs_ValidTime(t *testing.T) {
- tm := time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC)
- expected := "1672531200000"
- result := GetTimeInMs(tm)
- assert.Equal(t, expected, result)
-}
-
-func TestGetErrorResponse_ValidError(t *testing.T) {
- code := 404
- message := "Not Found"
- expected := &artifact.Error{
- Code: "404",
- Message: message,
+func TestValidatePackageTypes(t *testing.T) {
+ tests := []struct {
+ name string
+ types []string
+ wantErr bool
+ errMsg string
+ }{
+ {
+ name: "valid_types",
+ types: []string{"DOCKER", "HELM"},
+ wantErr: false,
+ },
+ {
+ name: "invalid_type",
+ types: []string{"INVALID"},
+ wantErr: true,
+ errMsg: "invalid package type",
+ },
}
- result := GetErrorResponse(code, message)
- assert.Equal(t, expected, result)
-}
-func TestGetSortByOrder_ValidOrder(t *testing.T) {
- assert.Equal(t, "ASC", GetSortByOrder(""))
- assert.Equal(t, "DESC", GetSortByOrder("DESC"))
- assert.Equal(t, "ASC", GetSortByOrder("INVALID"))
-}
-
-func TestGetSortByField_ValidField(t *testing.T) {
- assert.Equal(t, "name", GetSortByField("identifier", RepositoryResource))
- assert.Equal(t, "created_at", GetSortByField("invalid", RepositoryResource))
-}
-
-func TestGetPageLimit_ValidPageSize(t *testing.T) {
- pageSize := artifact.PageSize(20)
- assert.Equal(t, 20, GetPageLimit(&pageSize))
- assert.Equal(t, 10, GetPageLimit(nil))
-}
-
-func TestGetOffset_ValidOffset(t *testing.T) {
- pageSize := artifact.PageSize(20)
- pageNumber := artifact.PageNumber(2)
- assert.Equal(t, 40, GetOffset(&pageSize, &pageNumber))
- assert.Equal(t, 0, GetOffset(nil, nil))
-}
-
-func TestGetPageNumber_ValidPageNumber(t *testing.T) {
- pageNumber := artifact.PageNumber(2)
- assert.Equal(t, int64(2), GetPageNumber(&pageNumber))
- assert.Equal(t, int64(1), GetPageNumber(nil))
-}
-
-func TestGetSuccessResponse_ValidResponse(t *testing.T) {
- expected := &artifact.Success{
- Status: artifact.StatusSUCCESS,
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ err := metadata.ValidatePackageTypes(tt.types)
+ if tt.wantErr {
+ assert.Error(t, err)
+ assert.Equal(t, tt.errMsg, err.Error())
+ } else {
+ assert.NoError(t, err)
+ }
+ })
}
- result := GetSuccessResponse()
- assert.Equal(t, expected, result)
}
-func TestGetPageCount_ValidCount(t *testing.T) {
- assert.Equal(t, int64(5), GetPageCount(50, 10))
- assert.Equal(t, int64(0), GetPageCount(0, 10))
+func TestValidatePackageType(t *testing.T) {
+ tests := []struct {
+ name string
+ pkgType string
+ wantErr bool
+ errMsg string
+ }{
+ {
+ name: "valid_type",
+ pkgType: "DOCKER",
+ wantErr: false,
+ },
+ {
+ name: "invalid_type",
+ pkgType: "INVALID",
+ wantErr: true,
+ errMsg: "invalid package type",
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ err := metadata.ValidatePackageType(tt.pkgType)
+ if tt.wantErr {
+ assert.Error(t, err)
+ assert.Equal(t, tt.errMsg, err.Error())
+ } else {
+ assert.NoError(t, err)
+ }
+ })
+ }
}
-func TestGetRegistryRef_ValidRef(t *testing.T) {
- assert.Equal(t, "root/registry", GetRegistryRef("root", "registry"))
+func TestValidateIdentifier(t *testing.T) {
+ tests := []struct {
+ name string
+ identifier string
+ wantErr bool
+ errMsg string
+ }{
+ {
+ name: "valid_identifier",
+ identifier: "valid-identifier",
+ wantErr: false,
+ },
+ {
+ name: "invalid_identifier",
+ identifier: "Invalid Identifier",
+ wantErr: true,
+ errMsg: metadata.RegistryIdentifierErrorMsg,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ err := metadata.ValidateIdentifier(tt.identifier)
+ if tt.wantErr {
+ assert.Error(t, err)
+ assert.Equal(t, tt.errMsg, err.Error())
+ } else {
+ assert.NoError(t, err)
+ }
+ })
+ }
}
-func TestGetRepoURLWithoutProtocol_ValidURL(t *testing.T) {
- assert.Equal(t, "example.com/path", GetRepoURLWithoutProtocol("https://example.com/path"))
- assert.Equal(t, "", GetRepoURLWithoutProtocol("://invalid-url"))
+func TestCleanURLPath(t *testing.T) {
+ tests := []struct {
+ name string
+ input string
+ expected string
+ }{
+ {
+ name: "valid_url",
+ input: "https://example.com/path/",
+ expected: "https://example.com/path",
+ },
+ {
+ name: "invalid_url",
+ input: "://invalid-url",
+ expected: "://invalid-url",
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ input := tt.input
+ metadata.CleanURLPath(&input)
+ assert.Equal(t, tt.expected, input)
+ })
+ }
}
-func TestGetTagURL_ValidURL(t *testing.T) {
- assert.Equal(t, "https://example.com/artifact/version", GetTagURL("artifact", "version", "https://example.com"))
+func TestGetTimeInMs(t *testing.T) {
+ tests := []struct {
+ name string
+ time time.Time
+ expected string
+ }{
+ {
+ name: "valid_time",
+ time: time.Unix(1234567890, 0),
+ expected: "1234567890000",
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ result := metadata.GetTimeInMs(tt.time)
+ assert.Equal(t, tt.expected, result)
+ })
+ }
}
-func TestGetPullCommand_ValidCommand(t *testing.T) {
- assert.Equal(t, "docker pull example.com/image:tag",
- GetPullCommand("image", "tag", "DOCKER", "https://example.com"))
- assert.Equal(t, "helm pull oci://example.com/image --version tag",
- GetPullCommand("image", "tag", "HELM", "https://example.com"))
- assert.Equal(t, "", GetPullCommand("image", "tag", "INVALID", "https://example.com"))
+func TestGetPullCommand(t *testing.T) {
+ tests := []struct {
+ name string
+ image string
+ tag string
+ pkgType string
+ baseURL string
+ expected string
+ }{
+ {
+ name: "docker_command",
+ image: "image",
+ tag: "tag",
+ pkgType: "DOCKER",
+ baseURL: "https://example.com",
+ expected: "docker pull example.com/image:tag",
+ },
+ {
+ name: "helm_command",
+ image: "image",
+ tag: "tag",
+ pkgType: "HELM",
+ baseURL: "https://example.com",
+ expected: "helm pull oci://example.com/image --version tag",
+ },
+ {
+ name: "invalid_type",
+ image: "image",
+ tag: "tag",
+ pkgType: "INVALID",
+ baseURL: "https://example.com",
+ expected: "",
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ result := metadata.GetPullCommand(tt.image, tt.tag, tt.pkgType, tt.baseURL)
+ assert.Equal(t, tt.expected, result)
+ })
+ }
}
-func TestGetDockerPullCommand_ValidCommand(t *testing.T) {
- assert.Equal(t, "docker pull example.com/image:tag", GetDockerPullCommand("image", "tag", "https://example.com"))
+func TestGetDockerPullCommand(t *testing.T) {
+ tests := []struct {
+ name string
+ image string
+ tag string
+ baseURL string
+ expected string
+ }{
+ {
+ name: "valid_command",
+ image: "image",
+ tag: "tag",
+ baseURL: "https://example.com",
+ expected: "docker pull example.com/image:tag",
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ result := metadata.GetDockerPullCommand(tt.image, tt.tag, tt.baseURL)
+ assert.Equal(t, tt.expected, result)
+ })
+ }
}
-func TestGetHelmPullCommand_ValidCommand(t *testing.T) {
- assert.Equal(t, "helm pull oci://example.com/image --version tag",
- GetHelmPullCommand("image", "tag", "https://example.com"))
+func TestGetHelmPullCommand(t *testing.T) {
+ tests := []struct {
+ name string
+ image string
+ tag string
+ baseURL string
+ expected string
+ }{
+ {
+ name: "valid_command",
+ image: "image",
+ tag: "tag",
+ baseURL: "https://example.com",
+ expected: "helm pull oci://example.com/image --version tag",
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ result := metadata.GetHelmPullCommand(tt.image, tt.tag, tt.baseURL)
+ assert.Equal(t, tt.expected, result)
+ })
+ }
+}
+
+func TestGetErrorResponse(t *testing.T) {
+ tests := []struct {
+ name string
+ code int
+ message string
+ expected *artifact.Error
+ }{
+ {
+ name: "valid_error",
+ code: 404,
+ message: "Not Found",
+ expected: &artifact.Error{
+ Code: "404",
+ Message: "Not Found",
+ },
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ result := metadata.GetErrorResponse(tt.code, tt.message)
+ assert.Equal(t, tt.expected, result)
+ })
+ }
+}
+
+func TestGetSortByOrder(t *testing.T) {
+ tests := []struct {
+ name string
+ order string
+ expected string
+ }{
+ {
+ name: "empty_order",
+ order: "",
+ expected: "ASC",
+ },
+ {
+ name: "desc_order",
+ order: "DESC",
+ expected: "DESC",
+ },
+ {
+ name: "invalid_order",
+ order: "INVALID",
+ expected: "ASC",
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ result := metadata.GetSortByOrder(tt.order)
+ assert.Equal(t, tt.expected, result)
+ })
+ }
+}
+
+func TestGetSortByField(t *testing.T) {
+ tests := []struct {
+ name string
+ field string
+ resource string
+ expected string
+ }{
+ {
+ name: "identifier_field",
+ field: "identifier",
+ resource: "repository",
+ expected: "name",
+ },
+ {
+ name: "invalid_field",
+ field: "invalid",
+ resource: "repository",
+ expected: "created_at",
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ result := metadata.GetSortByField(tt.field, tt.resource)
+ assert.Equal(t, tt.expected, result)
+ })
+ }
+}
+
+func TestGetPageLimit(t *testing.T) {
+ tests := []struct {
+ name string
+ pageSize *artifact.PageSize
+ expected int
+ }{
+ {
+ name: "valid_page_size",
+ pageSize: func() *artifact.PageSize { ps := artifact.PageSize(20); return &ps }(),
+ expected: 20,
+ },
+ {
+ name: "nil_page_size",
+ pageSize: nil,
+ expected: 10,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ result := metadata.GetPageLimit(tt.pageSize)
+ assert.Equal(t, tt.expected, result)
+ })
+ }
+}
+
+func TestGetOffset(t *testing.T) {
+ tests := []struct {
+ name string
+ pageSize *artifact.PageSize
+ pageNumber *artifact.PageNumber
+ expected int
+ }{
+ {
+ name: "valid_offset",
+ pageSize: func() *artifact.PageSize { ps := artifact.PageSize(20); return &ps }(),
+ pageNumber: func() *artifact.PageNumber { pn := artifact.PageNumber(2); return &pn }(),
+ expected: 40,
+ },
+ {
+ name: "nil_values",
+ pageSize: nil,
+ pageNumber: nil,
+ expected: 0,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ result := metadata.GetOffset(tt.pageSize, tt.pageNumber)
+ assert.Equal(t, tt.expected, result)
+ })
+ }
+}
+
+func TestGetPageNumber(t *testing.T) {
+ tests := []struct {
+ name string
+ pageNumber *artifact.PageNumber
+ expected int64
+ }{
+ {
+ name: "valid_page_number",
+ pageNumber: func() *artifact.PageNumber { pn := artifact.PageNumber(2); return &pn }(),
+ expected: 2,
+ },
+ {
+ name: "nil_page_number",
+ pageNumber: nil,
+ expected: 1,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ result := metadata.GetPageNumber(tt.pageNumber)
+ assert.Equal(t, tt.expected, result)
+ })
+ }
+}
+
+func TestGetSuccessResponse(t *testing.T) {
+ tests := []struct {
+ name string
+ expected *artifact.Success
+ }{
+ {
+ name: "valid_response",
+ expected: &artifact.Success{
+ Status: artifact.StatusSUCCESS,
+ },
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ result := metadata.GetSuccessResponse()
+ assert.Equal(t, tt.expected, result)
+ })
+ }
+}
+
+func TestGetPageCount(t *testing.T) {
+ tests := []struct {
+ name string
+ count int64
+ limit int
+ expected int64
+ }{
+ {
+ name: "valid_count",
+ count: 50,
+ limit: 10,
+ expected: 5,
+ },
+ {
+ name: "zero_count",
+ count: 0,
+ limit: 10,
+ expected: 0,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ result := metadata.GetPageCount(tt.count, tt.limit)
+ assert.Equal(t, tt.expected, result)
+ })
+ }
+}
+
+func TestGetRegistryRef(t *testing.T) {
+ tests := []struct {
+ name string
+ root string
+ registry string
+ expected string
+ }{
+ {
+ name: "valid_ref",
+ root: "root",
+ registry: "registry",
+ expected: "root/registry",
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ result := metadata.GetRegistryRef(tt.root, tt.registry)
+ assert.Equal(t, tt.expected, result)
+ })
+ }
+}
+
+func TestGetRepoURLWithoutProtocol(t *testing.T) {
+ tests := []struct {
+ name string
+ url string
+ expected string
+ }{
+ {
+ name: "valid_url",
+ url: "https://example.com/path",
+ expected: "example.com/path",
+ },
+ {
+ name: "invalid_url",
+ url: "://invalid-url",
+ expected: "",
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ result := metadata.GetRepoURLWithoutProtocol(tt.url)
+ assert.Equal(t, tt.expected, result)
+ })
+ }
+}
+
+func TestGetTagURL(t *testing.T) {
+ tests := []struct {
+ name string
+ artifact string
+ version string
+ baseURL string
+ expected string
+ }{
+ {
+ name: "valid_url",
+ artifact: "artifact",
+ version: "version",
+ baseURL: "https://example.com",
+ expected: "https://example.com/artifact/version",
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ result := metadata.GetTagURL(tt.artifact, tt.version, tt.baseURL)
+ assert.Equal(t, tt.expected, result)
+ })
+ }
}
diff --git a/registry/app/api/controller/mocks/artifact_repository.go b/registry/app/api/controller/mocks/artifact_repository.go
new file mode 100644
index 000000000..bf23d13bd
--- /dev/null
+++ b/registry/app/api/controller/mocks/artifact_repository.go
@@ -0,0 +1,370 @@
+// Code generated by mockery v2.53.3. DO NOT EDIT.
+
+package mocks
+
+import (
+ context "context"
+
+ types "github.com/harness/gitness/registry/types"
+
+ mock "github.com/stretchr/testify/mock"
+)
+
+// ArtifactRepository is an autogenerated mock type for the ArtifactRepository type
+type ArtifactRepository struct {
+ mock.Mock
+}
+
+// Count provides a mock function with given fields: ctx
+func (_m *ArtifactRepository) Count(ctx context.Context) (int64, error) {
+ ret := _m.Called(ctx)
+
+ if len(ret) == 0 {
+ panic("no return value specified for Count")
+ }
+
+ var r0 int64
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context) (int64, error)); ok {
+ return rf(ctx)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context) int64); ok {
+ r0 = rf(ctx)
+ } else {
+ r0 = ret.Get(0).(int64)
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context) error); ok {
+ r1 = rf(ctx)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// CountAllArtifactsByParentID provides a mock function with given fields: ctx, parentID, registryIDs, search, latestVersion, packageTypes
+func (_m *ArtifactRepository) CountAllArtifactsByParentID(ctx context.Context, parentID int64, registryIDs *[]string, search string, latestVersion bool, packageTypes []string) (int64, error) {
+ ret := _m.Called(ctx, parentID, registryIDs, search, latestVersion, packageTypes)
+
+ if len(ret) == 0 {
+ panic("no return value specified for CountAllArtifactsByParentID")
+ }
+
+ var r0 int64
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, *[]string, string, bool, []string) (int64, error)); ok {
+ return rf(ctx, parentID, registryIDs, search, latestVersion, packageTypes)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, *[]string, string, bool, []string) int64); ok {
+ r0 = rf(ctx, parentID, registryIDs, search, latestVersion, packageTypes)
+ } else {
+ r0 = ret.Get(0).(int64)
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, *[]string, string, bool, []string) error); ok {
+ r1 = rf(ctx, parentID, registryIDs, search, latestVersion, packageTypes)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// CountAllArtifactsByRepo provides a mock function with given fields: ctx, parentID, repoKey, search, labels
+func (_m *ArtifactRepository) CountAllArtifactsByRepo(ctx context.Context, parentID int64, repoKey string, search string, labels []string) (int64, error) {
+ ret := _m.Called(ctx, parentID, repoKey, search, labels)
+
+ if len(ret) == 0 {
+ panic("no return value specified for CountAllArtifactsByRepo")
+ }
+
+ var r0 int64
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string, []string) (int64, error)); ok {
+ return rf(ctx, parentID, repoKey, search, labels)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string, []string) int64); ok {
+ r0 = rf(ctx, parentID, repoKey, search, labels)
+ } else {
+ r0 = ret.Get(0).(int64)
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, string, string, []string) error); ok {
+ r1 = rf(ctx, parentID, repoKey, search, labels)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// CountAllVersionsByRepoAndImage provides a mock function with given fields: ctx, parentID, repoKey, image, search
+func (_m *ArtifactRepository) CountAllVersionsByRepoAndImage(ctx context.Context, parentID int64, repoKey string, image string, search string) (int64, error) {
+ ret := _m.Called(ctx, parentID, repoKey, image, search)
+
+ if len(ret) == 0 {
+ panic("no return value specified for CountAllVersionsByRepoAndImage")
+ }
+
+ var r0 int64
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string, string) (int64, error)); ok {
+ return rf(ctx, parentID, repoKey, image, search)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string, string) int64); ok {
+ r0 = rf(ctx, parentID, repoKey, image, search)
+ } else {
+ r0 = ret.Get(0).(int64)
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, string, string, string) error); ok {
+ r1 = rf(ctx, parentID, repoKey, image, search)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// CreateOrUpdate provides a mock function with given fields: ctx, artifact
+func (_m *ArtifactRepository) CreateOrUpdate(ctx context.Context, artifact *types.Artifact) error {
+ ret := _m.Called(ctx, artifact)
+
+ if len(ret) == 0 {
+ panic("no return value specified for CreateOrUpdate")
+ }
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, *types.Artifact) error); ok {
+ r0 = rf(ctx, artifact)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// GetAllArtifactsByParentID provides a mock function with given fields: ctx, id, i, field, order, limit, offset, term, version, packageTypes
+func (_m *ArtifactRepository) GetAllArtifactsByParentID(ctx context.Context, id int64, i *[]string, field string, order string, limit int, offset int, term string, version bool, packageTypes []string) (*[]types.ArtifactMetadata, error) {
+ ret := _m.Called(ctx, id, i, field, order, limit, offset, term, version, packageTypes)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GetAllArtifactsByParentID")
+ }
+
+ var r0 *[]types.ArtifactMetadata
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, *[]string, string, string, int, int, string, bool, []string) (*[]types.ArtifactMetadata, error)); ok {
+ return rf(ctx, id, i, field, order, limit, offset, term, version, packageTypes)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, *[]string, string, string, int, int, string, bool, []string) *[]types.ArtifactMetadata); ok {
+ r0 = rf(ctx, id, i, field, order, limit, offset, term, version, packageTypes)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*[]types.ArtifactMetadata)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, *[]string, string, string, int, int, string, bool, []string) error); ok {
+ r1 = rf(ctx, id, i, field, order, limit, offset, term, version, packageTypes)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// GetAllArtifactsByRepo provides a mock function with given fields: ctx, parentID, repoKey, sortByField, sortByOrder, limit, offset, search, labels
+func (_m *ArtifactRepository) GetAllArtifactsByRepo(ctx context.Context, parentID int64, repoKey string, sortByField string, sortByOrder string, limit int, offset int, search string, labels []string) (*[]types.ArtifactMetadata, error) {
+ ret := _m.Called(ctx, parentID, repoKey, sortByField, sortByOrder, limit, offset, search, labels)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GetAllArtifactsByRepo")
+ }
+
+ var r0 *[]types.ArtifactMetadata
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string, string, int, int, string, []string) (*[]types.ArtifactMetadata, error)); ok {
+ return rf(ctx, parentID, repoKey, sortByField, sortByOrder, limit, offset, search, labels)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string, string, int, int, string, []string) *[]types.ArtifactMetadata); ok {
+ r0 = rf(ctx, parentID, repoKey, sortByField, sortByOrder, limit, offset, search, labels)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*[]types.ArtifactMetadata)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, string, string, string, int, int, string, []string) error); ok {
+ r1 = rf(ctx, parentID, repoKey, sortByField, sortByOrder, limit, offset, search, labels)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// GetAllVersionsByRepoAndImage provides a mock function with given fields: ctx, id, identifier, image, field, order, limit, offset, term
+func (_m *ArtifactRepository) GetAllVersionsByRepoAndImage(ctx context.Context, id int64, identifier string, image string, field string, order string, limit int, offset int, term string) (*[]types.NonOCIArtifactMetadata, error) {
+ ret := _m.Called(ctx, id, identifier, image, field, order, limit, offset, term)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GetAllVersionsByRepoAndImage")
+ }
+
+ var r0 *[]types.NonOCIArtifactMetadata
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string, string, string, int, int, string) (*[]types.NonOCIArtifactMetadata, error)); ok {
+ return rf(ctx, id, identifier, image, field, order, limit, offset, term)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string, string, string, int, int, string) *[]types.NonOCIArtifactMetadata); ok {
+ r0 = rf(ctx, id, identifier, image, field, order, limit, offset, term)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*[]types.NonOCIArtifactMetadata)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, string, string, string, string, int, int, string) error); ok {
+ r1 = rf(ctx, id, identifier, image, field, order, limit, offset, term)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// GetArtifactMetadata provides a mock function with given fields: ctx, id, identifier, image, version
+func (_m *ArtifactRepository) GetArtifactMetadata(ctx context.Context, id int64, identifier string, image string, version string) (*types.ArtifactMetadata, error) {
+ ret := _m.Called(ctx, id, identifier, image, version)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GetArtifactMetadata")
+ }
+
+ var r0 *types.ArtifactMetadata
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string, string) (*types.ArtifactMetadata, error)); ok {
+ return rf(ctx, id, identifier, image, version)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string, string) *types.ArtifactMetadata); ok {
+ r0 = rf(ctx, id, identifier, image, version)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.ArtifactMetadata)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, string, string, string) error); ok {
+ r1 = rf(ctx, id, identifier, image, version)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// GetByName provides a mock function with given fields: ctx, imageID, version
+func (_m *ArtifactRepository) GetByName(ctx context.Context, imageID int64, version string) (*types.Artifact, error) {
+ ret := _m.Called(ctx, imageID, version)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GetByName")
+ }
+
+ var r0 *types.Artifact
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string) (*types.Artifact, error)); ok {
+ return rf(ctx, imageID, version)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string) *types.Artifact); ok {
+ r0 = rf(ctx, imageID, version)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.Artifact)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, string) error); ok {
+ r1 = rf(ctx, imageID, version)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// GetByRegistryIDAndImage provides a mock function with given fields: ctx, registryID, image
+func (_m *ArtifactRepository) GetByRegistryIDAndImage(ctx context.Context, registryID int64, image string) (*[]types.Artifact, error) {
+ ret := _m.Called(ctx, registryID, image)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GetByRegistryIDAndImage")
+ }
+
+ var r0 *[]types.Artifact
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string) (*[]types.Artifact, error)); ok {
+ return rf(ctx, registryID, image)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string) *[]types.Artifact); ok {
+ r0 = rf(ctx, registryID, image)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*[]types.Artifact)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, string) error); ok {
+ r1 = rf(ctx, registryID, image)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// GetLatestArtifactMetadata provides a mock function with given fields: ctx, id, identifier, image
+func (_m *ArtifactRepository) GetLatestArtifactMetadata(ctx context.Context, id int64, identifier string, image string) (*types.ArtifactMetadata, error) {
+ ret := _m.Called(ctx, id, identifier, image)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GetLatestArtifactMetadata")
+ }
+
+ var r0 *types.ArtifactMetadata
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string) (*types.ArtifactMetadata, error)); ok {
+ return rf(ctx, id, identifier, image)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string) *types.ArtifactMetadata); ok {
+ r0 = rf(ctx, id, identifier, image)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.ArtifactMetadata)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, string, string) error); ok {
+ r1 = rf(ctx, id, identifier, image)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// NewArtifactRepository creates a new instance of ArtifactRepository. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewArtifactRepository(t interface {
+ mock.TestingT
+ Cleanup(func())
+}) *ArtifactRepository {
+ mock := &ArtifactRepository{}
+ mock.Mock.Test(t)
+
+ t.Cleanup(func() { mock.AssertExpectations(t) })
+
+ return mock
+}
diff --git a/registry/app/api/controller/mocks/audit_service.go b/registry/app/api/controller/mocks/audit_service.go
new file mode 100644
index 000000000..f651f1a55
--- /dev/null
+++ b/registry/app/api/controller/mocks/audit_service.go
@@ -0,0 +1,42 @@
+// Code generated by testify. DO NOT EDIT.
+
+package mocks
+
+import (
+ "context"
+
+ "github.com/harness/gitness/audit"
+ "github.com/harness/gitness/types"
+
+ "github.com/stretchr/testify/mock"
+)
+
+// AuditService is a mock of audit.Service interface.
+type AuditService struct {
+ mock.Mock
+}
+
+// Log provides a mock function
+func (m *AuditService) Log(
+ ctx context.Context,
+ user types.Principal,
+ resource audit.Resource,
+ action audit.Action,
+ spacePath string,
+ options ...audit.Option,
+) error {
+ args := []interface{}{ctx, user, resource, action, spacePath}
+ for _, opt := range options {
+ args = append(args, opt)
+ }
+ ret := m.Called(args...)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, types.Principal, audit.Resource, audit.Action, string, ...audit.Option) error); ok {
+ r0 = rf(ctx, user, resource, action, spacePath, options...)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
diff --git a/registry/app/api/controller/mocks/authorizer.go b/registry/app/api/controller/mocks/authorizer.go
new file mode 100644
index 000000000..5ea3b1e69
--- /dev/null
+++ b/registry/app/api/controller/mocks/authorizer.go
@@ -0,0 +1,65 @@
+// Code generated by testify. DO NOT EDIT.
+
+package mocks
+
+import (
+ "context"
+
+ "github.com/harness/gitness/app/auth"
+ "github.com/harness/gitness/types"
+ "github.com/harness/gitness/types/enum"
+
+ "github.com/stretchr/testify/mock"
+)
+
+// Authorizer is an autogenerated mock type for the Authorizer type
+type Authorizer struct {
+ mock.Mock
+}
+
+// Check provides a mock function with given fields: ctx, session, scope, resource, permission
+func (m *Authorizer) Check(ctx context.Context, session *auth.Session, scope *types.Scope, resource *types.Resource, permission enum.Permission) (bool, error) {
+ ret := m.Called(ctx, session, scope, resource, permission)
+
+ var r0 bool
+ if rf, ok := ret.Get(0).(func(context.Context, *auth.Session, *types.Scope, *types.Resource, enum.Permission) bool); ok {
+ r0 = rf(ctx, session, scope, resource, permission)
+ } else {
+ r0 = ret.Get(0).(bool)
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context, *auth.Session, *types.Scope, *types.Resource, enum.Permission) error); ok {
+ r1 = rf(ctx, session, scope, resource, permission)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// CheckAll provides a mock function with given fields: ctx, session, permissionChecks
+func (m *Authorizer) CheckAll(ctx context.Context, session *auth.Session, permissionChecks ...types.PermissionCheck) (bool, error) {
+ var args []interface{}
+ args = append(args, ctx, session)
+ for _, check := range permissionChecks {
+ args = append(args, check)
+ }
+ ret := m.Called(args...)
+
+ var r0 bool
+ if rf, ok := ret.Get(0).(func(context.Context, *auth.Session, ...types.PermissionCheck) bool); ok {
+ r0 = rf(ctx, session, permissionChecks...)
+ } else {
+ r0 = ret.Get(0).(bool)
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context, *auth.Session, ...types.PermissionCheck) error); ok {
+ r1 = rf(ctx, session, permissionChecks...)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
diff --git a/registry/app/api/controller/mocks/blob_repository.go b/registry/app/api/controller/mocks/blob_repository.go
new file mode 100644
index 000000000..2bbc43f55
--- /dev/null
+++ b/registry/app/api/controller/mocks/blob_repository.go
@@ -0,0 +1,232 @@
+// Code generated by mockery v2.53.3. DO NOT EDIT.
+
+package mocks
+
+import (
+ context "context"
+
+ types "github.com/harness/gitness/registry/types"
+
+ digest "github.com/opencontainers/go-digest"
+ mock "github.com/stretchr/testify/mock"
+)
+
+// BlobRepository is an autogenerated mock type for the BlobRepository type
+type BlobRepository struct {
+ mock.Mock
+}
+
+// CreateOrFind provides a mock function with given fields: ctx, b
+func (_m *BlobRepository) CreateOrFind(ctx context.Context, b *types.Blob) (*types.Blob, bool, error) {
+ ret := _m.Called(ctx, b)
+
+ if len(ret) == 0 {
+ panic("no return value specified for CreateOrFind")
+ }
+
+ var r0 *types.Blob
+ var r1 bool
+ var r2 error
+ if rf, ok := ret.Get(0).(func(context.Context, *types.Blob) (*types.Blob, bool, error)); ok {
+ return rf(ctx, b)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, *types.Blob) *types.Blob); ok {
+ r0 = rf(ctx, b)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.Blob)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, *types.Blob) bool); ok {
+ r1 = rf(ctx, b)
+ } else {
+ r1 = ret.Get(1).(bool)
+ }
+
+ if rf, ok := ret.Get(2).(func(context.Context, *types.Blob) error); ok {
+ r2 = rf(ctx, b)
+ } else {
+ r2 = ret.Error(2)
+ }
+
+ return r0, r1, r2
+}
+
+// DeleteByID provides a mock function with given fields: ctx, id
+func (_m *BlobRepository) DeleteByID(ctx context.Context, id int64) error {
+ ret := _m.Called(ctx, id)
+
+ if len(ret) == 0 {
+ panic("no return value specified for DeleteByID")
+ }
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64) error); ok {
+ r0 = rf(ctx, id)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// ExistsBlob provides a mock function with given fields: ctx, repoID, d, image
+func (_m *BlobRepository) ExistsBlob(ctx context.Context, repoID int64, d digest.Digest, image string) (bool, error) {
+ ret := _m.Called(ctx, repoID, d, image)
+
+ if len(ret) == 0 {
+ panic("no return value specified for ExistsBlob")
+ }
+
+ var r0 bool
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, digest.Digest, string) (bool, error)); ok {
+ return rf(ctx, repoID, d, image)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, digest.Digest, string) bool); ok {
+ r0 = rf(ctx, repoID, d, image)
+ } else {
+ r0 = ret.Get(0).(bool)
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, digest.Digest, string) error); ok {
+ r1 = rf(ctx, repoID, d, image)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// FindByDigestAndRepoID provides a mock function with given fields: ctx, d, repoID, imageName
+func (_m *BlobRepository) FindByDigestAndRepoID(ctx context.Context, d digest.Digest, repoID int64, imageName string) (*types.Blob, error) {
+ ret := _m.Called(ctx, d, repoID, imageName)
+
+ if len(ret) == 0 {
+ panic("no return value specified for FindByDigestAndRepoID")
+ }
+
+ var r0 *types.Blob
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, digest.Digest, int64, string) (*types.Blob, error)); ok {
+ return rf(ctx, d, repoID, imageName)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, digest.Digest, int64, string) *types.Blob); ok {
+ r0 = rf(ctx, d, repoID, imageName)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.Blob)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, digest.Digest, int64, string) error); ok {
+ r1 = rf(ctx, d, repoID, imageName)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// FindByDigestAndRootParentID provides a mock function with given fields: ctx, d, rootParentID
+func (_m *BlobRepository) FindByDigestAndRootParentID(ctx context.Context, d digest.Digest, rootParentID int64) (*types.Blob, error) {
+ ret := _m.Called(ctx, d, rootParentID)
+
+ if len(ret) == 0 {
+ panic("no return value specified for FindByDigestAndRootParentID")
+ }
+
+ var r0 *types.Blob
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, digest.Digest, int64) (*types.Blob, error)); ok {
+ return rf(ctx, d, rootParentID)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, digest.Digest, int64) *types.Blob); ok {
+ r0 = rf(ctx, d, rootParentID)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.Blob)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, digest.Digest, int64) error); ok {
+ r1 = rf(ctx, d, rootParentID)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// FindByID provides a mock function with given fields: ctx, id
+func (_m *BlobRepository) FindByID(ctx context.Context, id int64) (*types.Blob, error) {
+ ret := _m.Called(ctx, id)
+
+ if len(ret) == 0 {
+ panic("no return value specified for FindByID")
+ }
+
+ var r0 *types.Blob
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64) (*types.Blob, error)); ok {
+ return rf(ctx, id)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64) *types.Blob); ok {
+ r0 = rf(ctx, id)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.Blob)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok {
+ r1 = rf(ctx, id)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// TotalSizeByRootParentID provides a mock function with given fields: ctx, id
+func (_m *BlobRepository) TotalSizeByRootParentID(ctx context.Context, id int64) (int64, error) {
+ ret := _m.Called(ctx, id)
+
+ if len(ret) == 0 {
+ panic("no return value specified for TotalSizeByRootParentID")
+ }
+
+ var r0 int64
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64) (int64, error)); ok {
+ return rf(ctx, id)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64) int64); ok {
+ r0 = rf(ctx, id)
+ } else {
+ r0 = ret.Get(0).(int64)
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok {
+ r1 = rf(ctx, id)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// NewBlobRepository creates a new instance of BlobRepository. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewBlobRepository(t interface {
+ mock.TestingT
+ Cleanup(func())
+}) *BlobRepository {
+ mock := &BlobRepository{}
+ mock.Mock.Test(t)
+
+ t.Cleanup(func() { mock.AssertExpectations(t) })
+
+ return mock
+}
diff --git a/registry/app/api/controller/mocks/cleanup_policy_repository.go b/registry/app/api/controller/mocks/cleanup_policy_repository.go
new file mode 100644
index 000000000..11ae7be64
--- /dev/null
+++ b/registry/app/api/controller/mocks/cleanup_policy_repository.go
@@ -0,0 +1,308 @@
+// Code generated by mockery v2.53.3. DO NOT EDIT.
+
+package mocks
+
+import (
+ context "context"
+
+ types "github.com/harness/gitness/registry/types"
+
+ mock "github.com/stretchr/testify/mock"
+)
+
+// CleanupPolicyRepository is an autogenerated mock type for the CleanupPolicyRepository type
+type CleanupPolicyRepository struct {
+ mock.Mock
+}
+
+type CleanupPolicyRepository_Expecter struct {
+ mock *mock.Mock
+}
+
+func (_m *CleanupPolicyRepository) EXPECT() *CleanupPolicyRepository_Expecter {
+ return &CleanupPolicyRepository_Expecter{mock: &_m.Mock}
+}
+
+// Create provides a mock function with given fields: ctx, cleanupPolicy
+func (_m *CleanupPolicyRepository) Create(ctx context.Context, cleanupPolicy *types.CleanupPolicy) (int64, error) {
+ ret := _m.Called(ctx, cleanupPolicy)
+
+ if len(ret) == 0 {
+ panic("no return value specified for Create")
+ }
+
+ var r0 int64
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, *types.CleanupPolicy) (int64, error)); ok {
+ return rf(ctx, cleanupPolicy)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, *types.CleanupPolicy) int64); ok {
+ r0 = rf(ctx, cleanupPolicy)
+ } else {
+ r0 = ret.Get(0).(int64)
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, *types.CleanupPolicy) error); ok {
+ r1 = rf(ctx, cleanupPolicy)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// CleanupPolicyRepository_Create_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Create'
+type CleanupPolicyRepository_Create_Call struct {
+ *mock.Call
+}
+
+// Create is a helper method to define mock.On call
+// - ctx context.Context
+// - cleanupPolicy *types.CleanupPolicy
+func (_e *CleanupPolicyRepository_Expecter) Create(ctx interface{}, cleanupPolicy interface{}) *CleanupPolicyRepository_Create_Call {
+ return &CleanupPolicyRepository_Create_Call{Call: _e.mock.On("Create", ctx, cleanupPolicy)}
+}
+
+func (_c *CleanupPolicyRepository_Create_Call) Run(run func(ctx context.Context, cleanupPolicy *types.CleanupPolicy)) *CleanupPolicyRepository_Create_Call {
+ _c.Call.Run(func(args mock.Arguments) {
+ run(args[0].(context.Context), args[1].(*types.CleanupPolicy))
+ })
+ return _c
+}
+
+func (_c *CleanupPolicyRepository_Create_Call) Return(id int64, err error) *CleanupPolicyRepository_Create_Call {
+ _c.Call.Return(id, err)
+ return _c
+}
+
+func (_c *CleanupPolicyRepository_Create_Call) RunAndReturn(run func(context.Context, *types.CleanupPolicy) (int64, error)) *CleanupPolicyRepository_Create_Call {
+ _c.Call.Return(run)
+ return _c
+}
+
+// Delete provides a mock function with given fields: ctx, id
+func (_m *CleanupPolicyRepository) Delete(ctx context.Context, id int64) error {
+ ret := _m.Called(ctx, id)
+
+ if len(ret) == 0 {
+ panic("no return value specified for Delete")
+ }
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64) error); ok {
+ r0 = rf(ctx, id)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// CleanupPolicyRepository_Delete_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Delete'
+type CleanupPolicyRepository_Delete_Call struct {
+ *mock.Call
+}
+
+// Delete is a helper method to define mock.On call
+// - ctx context.Context
+// - id int64
+func (_e *CleanupPolicyRepository_Expecter) Delete(ctx interface{}, id interface{}) *CleanupPolicyRepository_Delete_Call {
+ return &CleanupPolicyRepository_Delete_Call{Call: _e.mock.On("Delete", ctx, id)}
+}
+
+func (_c *CleanupPolicyRepository_Delete_Call) Run(run func(ctx context.Context, id int64)) *CleanupPolicyRepository_Delete_Call {
+ _c.Call.Run(func(args mock.Arguments) {
+ run(args[0].(context.Context), args[1].(int64))
+ })
+ return _c
+}
+
+func (_c *CleanupPolicyRepository_Delete_Call) Return(err error) *CleanupPolicyRepository_Delete_Call {
+ _c.Call.Return(err)
+ return _c
+}
+
+func (_c *CleanupPolicyRepository_Delete_Call) RunAndReturn(run func(context.Context, int64) error) *CleanupPolicyRepository_Delete_Call {
+ _c.Call.Return(run)
+ return _c
+}
+
+// GetByRegistryID provides a mock function with given fields: ctx, id
+func (_m *CleanupPolicyRepository) GetByRegistryID(ctx context.Context, id int64) (*[]types.CleanupPolicy, error) {
+ ret := _m.Called(ctx, id)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GetByRegistryID")
+ }
+
+ var r0 *[]types.CleanupPolicy
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64) (*[]types.CleanupPolicy, error)); ok {
+ return rf(ctx, id)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64) *[]types.CleanupPolicy); ok {
+ r0 = rf(ctx, id)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*[]types.CleanupPolicy)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok {
+ r1 = rf(ctx, id)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// CleanupPolicyRepository_GetByRegistryID_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetByRegistryID'
+type CleanupPolicyRepository_GetByRegistryID_Call struct {
+ *mock.Call
+}
+
+// GetByRegistryID is a helper method to define mock.On call
+// - ctx context.Context
+// - id int64
+func (_e *CleanupPolicyRepository_Expecter) GetByRegistryID(ctx interface{}, id interface{}) *CleanupPolicyRepository_GetByRegistryID_Call {
+ return &CleanupPolicyRepository_GetByRegistryID_Call{Call: _e.mock.On("GetByRegistryID", ctx, id)}
+}
+
+func (_c *CleanupPolicyRepository_GetByRegistryID_Call) Run(run func(ctx context.Context, id int64)) *CleanupPolicyRepository_GetByRegistryID_Call {
+ _c.Call.Run(func(args mock.Arguments) {
+ run(args[0].(context.Context), args[1].(int64))
+ })
+ return _c
+}
+
+func (_c *CleanupPolicyRepository_GetByRegistryID_Call) Return(cleanupPolicies *[]types.CleanupPolicy, err error) *CleanupPolicyRepository_GetByRegistryID_Call {
+ _c.Call.Return(cleanupPolicies, err)
+ return _c
+}
+
+func (_c *CleanupPolicyRepository_GetByRegistryID_Call) RunAndReturn(run func(context.Context, int64) (*[]types.CleanupPolicy, error)) *CleanupPolicyRepository_GetByRegistryID_Call {
+ _c.Call.Return(run)
+ return _c
+}
+
+// GetIDsByRegistryID provides a mock function with given fields: ctx, id
+func (_m *CleanupPolicyRepository) GetIDsByRegistryID(ctx context.Context, id int64) ([]int64, error) {
+ ret := _m.Called(ctx, id)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GetIDsByRegistryID")
+ }
+
+ var r0 []int64
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64) ([]int64, error)); ok {
+ return rf(ctx, id)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64) []int64); ok {
+ r0 = rf(ctx, id)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]int64)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok {
+ r1 = rf(ctx, id)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// CleanupPolicyRepository_GetIDsByRegistryID_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetIDsByRegistryID'
+type CleanupPolicyRepository_GetIDsByRegistryID_Call struct {
+ *mock.Call
+}
+
+// GetIDsByRegistryID is a helper method to define mock.On call
+// - ctx context.Context
+// - id int64
+func (_e *CleanupPolicyRepository_Expecter) GetIDsByRegistryID(ctx interface{}, id interface{}) *CleanupPolicyRepository_GetIDsByRegistryID_Call {
+ return &CleanupPolicyRepository_GetIDsByRegistryID_Call{Call: _e.mock.On("GetIDsByRegistryID", ctx, id)}
+}
+
+func (_c *CleanupPolicyRepository_GetIDsByRegistryID_Call) Run(run func(ctx context.Context, id int64)) *CleanupPolicyRepository_GetIDsByRegistryID_Call {
+ _c.Call.Run(func(args mock.Arguments) {
+ run(args[0].(context.Context), args[1].(int64))
+ })
+ return _c
+}
+
+func (_c *CleanupPolicyRepository_GetIDsByRegistryID_Call) Return(ids []int64, err error) *CleanupPolicyRepository_GetIDsByRegistryID_Call {
+ _c.Call.Return(ids, err)
+ return _c
+}
+
+func (_c *CleanupPolicyRepository_GetIDsByRegistryID_Call) RunAndReturn(run func(context.Context, int64) ([]int64, error)) *CleanupPolicyRepository_GetIDsByRegistryID_Call {
+ _c.Call.Return(run)
+ return _c
+}
+
+// ModifyCleanupPolicies provides a mock function with given fields: ctx, cleanupPolicies, ids
+func (_m *CleanupPolicyRepository) ModifyCleanupPolicies(ctx context.Context, cleanupPolicies *[]types.CleanupPolicy, ids []int64) error {
+ ret := _m.Called(ctx, cleanupPolicies, ids)
+
+ if len(ret) == 0 {
+ panic("no return value specified for ModifyCleanupPolicies")
+ }
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, *[]types.CleanupPolicy, []int64) error); ok {
+ r0 = rf(ctx, cleanupPolicies, ids)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// CleanupPolicyRepository_ModifyCleanupPolicies_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ModifyCleanupPolicies'
+type CleanupPolicyRepository_ModifyCleanupPolicies_Call struct {
+ *mock.Call
+}
+
+// ModifyCleanupPolicies is a helper method to define mock.On call
+// - ctx context.Context
+// - cleanupPolicies *[]types.CleanupPolicy
+// - ids []int64
+func (_e *CleanupPolicyRepository_Expecter) ModifyCleanupPolicies(ctx interface{}, cleanupPolicies interface{}, ids interface{}) *CleanupPolicyRepository_ModifyCleanupPolicies_Call {
+ return &CleanupPolicyRepository_ModifyCleanupPolicies_Call{Call: _e.mock.On("ModifyCleanupPolicies", ctx, cleanupPolicies, ids)}
+}
+
+func (_c *CleanupPolicyRepository_ModifyCleanupPolicies_Call) Run(run func(ctx context.Context, cleanupPolicies *[]types.CleanupPolicy, ids []int64)) *CleanupPolicyRepository_ModifyCleanupPolicies_Call {
+ _c.Call.Run(func(args mock.Arguments) {
+ run(args[0].(context.Context), args[1].(*[]types.CleanupPolicy), args[2].([]int64))
+ })
+ return _c
+}
+
+func (_c *CleanupPolicyRepository_ModifyCleanupPolicies_Call) Return(_a0 error) *CleanupPolicyRepository_ModifyCleanupPolicies_Call {
+ _c.Call.Return(_a0)
+ return _c
+}
+
+func (_c *CleanupPolicyRepository_ModifyCleanupPolicies_Call) RunAndReturn(run func(context.Context, *[]types.CleanupPolicy, []int64) error) *CleanupPolicyRepository_ModifyCleanupPolicies_Call {
+ _c.Call.Return(run)
+ return _c
+}
+
+// NewCleanupPolicyRepository creates a new instance of CleanupPolicyRepository. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewCleanupPolicyRepository(t interface {
+ mock.TestingT
+ Cleanup(func())
+}) *CleanupPolicyRepository {
+ mock := &CleanupPolicyRepository{}
+ mock.Mock.Test(t)
+
+ t.Cleanup(func() { mock.AssertExpectations(t) })
+
+ return mock
+}
diff --git a/registry/app/api/controller/mocks/controller.go b/registry/app/api/controller/mocks/controller.go
new file mode 100644
index 000000000..e77029bb7
--- /dev/null
+++ b/registry/app/api/controller/mocks/controller.go
@@ -0,0 +1,100 @@
+// Code generated by mockery v2.53.3. DO NOT EDIT.
+
+package mocks
+
+import (
+ context "context"
+ multipart "mime/multipart"
+
+ pkgpython "github.com/harness/gitness/registry/app/api/controller/pkg/python"
+ python "github.com/harness/gitness/registry/app/pkg/types/python"
+
+ mock "github.com/stretchr/testify/mock"
+)
+
+// Controller is an autogenerated mock type for the Controller type
+type Controller struct {
+ mock.Mock
+}
+
+// DownloadPackageFile provides a mock function with given fields: ctx, info
+func (_m *Controller) DownloadPackageFile(ctx context.Context, info python.ArtifactInfo) *pkgpython.GetArtifactResponse {
+ ret := _m.Called(ctx, info)
+
+ if len(ret) == 0 {
+ panic("no return value specified for DownloadPackageFile")
+ }
+
+ var r0 *pkgpython.GetArtifactResponse
+ if rf, ok := ret.Get(0).(func(context.Context, python.ArtifactInfo) *pkgpython.GetArtifactResponse); ok {
+ r0 = rf(ctx, info)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*pkgpython.GetArtifactResponse)
+ }
+ }
+
+ return r0
+}
+
+// GetPackageMetadata provides a mock function with given fields: ctx, info
+func (_m *Controller) GetPackageMetadata(ctx context.Context, info python.ArtifactInfo) (python.PackageMetadata, error) {
+ ret := _m.Called(ctx, info)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GetPackageMetadata")
+ }
+
+ var r0 python.PackageMetadata
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, python.ArtifactInfo) (python.PackageMetadata, error)); ok {
+ return rf(ctx, info)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, python.ArtifactInfo) python.PackageMetadata); ok {
+ r0 = rf(ctx, info)
+ } else {
+ r0 = ret.Get(0).(python.PackageMetadata)
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, python.ArtifactInfo) error); ok {
+ r1 = rf(ctx, info)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// UploadPackageFile provides a mock function with given fields: ctx, info, file, fileHeader
+func (_m *Controller) UploadPackageFile(ctx context.Context, info python.ArtifactInfo, file multipart.File, fileHeader *multipart.FileHeader) *pkgpython.PutArtifactResponse {
+ ret := _m.Called(ctx, info, file, fileHeader)
+
+ if len(ret) == 0 {
+ panic("no return value specified for UploadPackageFile")
+ }
+
+ var r0 *pkgpython.PutArtifactResponse
+ if rf, ok := ret.Get(0).(func(context.Context, python.ArtifactInfo, multipart.File, *multipart.FileHeader) *pkgpython.PutArtifactResponse); ok {
+ r0 = rf(ctx, info, file, fileHeader)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*pkgpython.PutArtifactResponse)
+ }
+ }
+
+ return r0
+}
+
+// NewController creates a new instance of Controller. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewController(t interface {
+ mock.TestingT
+ Cleanup(func())
+}) *Controller {
+ mock := &Controller{}
+ mock.Mock.Test(t)
+
+ t.Cleanup(func() { mock.AssertExpectations(t) })
+
+ return mock
+}
diff --git a/registry/app/api/controller/mocks/file_manager.go b/registry/app/api/controller/mocks/file_manager.go
new file mode 100644
index 000000000..822875dd9
--- /dev/null
+++ b/registry/app/api/controller/mocks/file_manager.go
@@ -0,0 +1,67 @@
+// Code generated by mockery. DO NOT EDIT.
+
+package mocks
+
+import (
+ "context"
+ "io"
+ "mime/multipart"
+
+ "github.com/harness/gitness/registry/app/storage"
+ "github.com/harness/gitness/registry/types"
+
+ "github.com/stretchr/testify/mock"
+)
+
+// FileManager is a mock type for filemanager.FileManager
+type FileManager struct {
+ mock.Mock
+}
+
+// UploadFile provides a mock function
+func (m *FileManager) UploadFile(ctx context.Context, filePath string, regName string, regID int64, rootParentID int64, rootIdentifier string, file multipart.File, fileReader io.Reader, filename string) (types.FileInfo, error) {
+ args := m.Called(ctx, filePath, regName, regID, rootParentID, rootIdentifier, file, fileReader, filename)
+ return args.Get(0).(types.FileInfo), args.Error(1)
+}
+
+// DownloadFile provides a mock function
+func (m *FileManager) DownloadFile(ctx context.Context, filePath string, regInfo types.Registry, rootIdentifier string) (*storage.FileReader, int64, string, error) {
+ args := m.Called(ctx, filePath, regInfo, rootIdentifier)
+ return args.Get(0).(*storage.FileReader), args.Get(1).(int64), args.Get(2).(string), args.Error(3)
+}
+
+// DeleteFile provides a mock function
+func (m *FileManager) DeleteFile(ctx context.Context, filePath string, regID int) error {
+ args := m.Called(ctx, filePath, regID)
+ return args.Error(0)
+}
+
+// HeadFile provides a mock function
+func (m *FileManager) HeadFile(ctx context.Context, filePath string, regID int64) (string, error) {
+ args := m.Called(ctx, filePath, regID)
+ return args.String(0), args.Error(1)
+}
+
+// GetFileMetadata provides a mock function
+func (m *FileManager) GetFileMetadata(ctx context.Context, filePath string, regID int64) (types.FileInfo, error) {
+ args := m.Called(ctx, filePath, regID)
+ return args.Get(0).(types.FileInfo), args.Error(1)
+}
+
+// DeleteFileByRegistryID provides a mock function
+func (m *FileManager) DeleteFileByRegistryID(ctx context.Context, regID int64, regName string) error {
+ args := m.Called(ctx, regID, regName)
+ return args.Error(0)
+}
+
+// GetFilesMetadata provides a mock function
+func (m *FileManager) GetFilesMetadata(ctx context.Context, filePath string, regID int64, sortByField string, sortByOrder string, limit int, offset int, search string) (*[]types.FileNodeMetadata, error) {
+ args := m.Called(ctx, filePath, regID, sortByField, sortByOrder, limit, offset, search)
+ return args.Get(0).(*[]types.FileNodeMetadata), args.Error(1)
+}
+
+// CountFilesByPath provides a mock function
+func (m *FileManager) CountFilesByPath(ctx context.Context, filePath string, regID int64) (int64, error) {
+ args := m.Called(ctx, filePath, regID)
+ return args.Get(0).(int64), args.Error(1)
+}
diff --git a/registry/app/api/controller/mocks/generic_blob_repository.go b/registry/app/api/controller/mocks/generic_blob_repository.go
new file mode 100644
index 000000000..fcc089401
--- /dev/null
+++ b/registry/app/api/controller/mocks/generic_blob_repository.go
@@ -0,0 +1,164 @@
+// Code generated by mockery v2.53.3. DO NOT EDIT.
+
+package mocks
+
+import (
+ context "context"
+
+ types "github.com/harness/gitness/registry/types"
+
+ mock "github.com/stretchr/testify/mock"
+)
+
+// GenericBlobRepository is an autogenerated mock type for the GenericBlobRepository type
+type GenericBlobRepository struct {
+ mock.Mock
+}
+
+// Create provides a mock function with given fields: ctx, gb
+func (_m *GenericBlobRepository) Create(ctx context.Context, gb *types.GenericBlob) (bool, error) {
+ ret := _m.Called(ctx, gb)
+
+ if len(ret) == 0 {
+ panic("no return value specified for Create")
+ }
+
+ var r0 bool
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, *types.GenericBlob) (bool, error)); ok {
+ return rf(ctx, gb)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, *types.GenericBlob) bool); ok {
+ r0 = rf(ctx, gb)
+ } else {
+ r0 = ret.Get(0).(bool)
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, *types.GenericBlob) error); ok {
+ r1 = rf(ctx, gb)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// DeleteByID provides a mock function with given fields: ctx, id
+func (_m *GenericBlobRepository) DeleteByID(ctx context.Context, id string) error {
+ ret := _m.Called(ctx, id)
+
+ if len(ret) == 0 {
+ panic("no return value specified for DeleteByID")
+ }
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, string) error); ok {
+ r0 = rf(ctx, id)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// FindByID provides a mock function with given fields: ctx, id
+func (_m *GenericBlobRepository) FindByID(ctx context.Context, id string) (*types.GenericBlob, error) {
+ ret := _m.Called(ctx, id)
+
+ if len(ret) == 0 {
+ panic("no return value specified for FindByID")
+ }
+
+ var r0 *types.GenericBlob
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, string) (*types.GenericBlob, error)); ok {
+ return rf(ctx, id)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, string) *types.GenericBlob); ok {
+ r0 = rf(ctx, id)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.GenericBlob)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
+ r1 = rf(ctx, id)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// FindBySha256AndRootParentID provides a mock function with given fields: ctx, sha256, rootParentID
+func (_m *GenericBlobRepository) FindBySha256AndRootParentID(ctx context.Context, sha256 string, rootParentID int64) (*types.GenericBlob, error) {
+ ret := _m.Called(ctx, sha256, rootParentID)
+
+ if len(ret) == 0 {
+ panic("no return value specified for FindBySha256AndRootParentID")
+ }
+
+ var r0 *types.GenericBlob
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, string, int64) (*types.GenericBlob, error)); ok {
+ return rf(ctx, sha256, rootParentID)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, string, int64) *types.GenericBlob); ok {
+ r0 = rf(ctx, sha256, rootParentID)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.GenericBlob)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, string, int64) error); ok {
+ r1 = rf(ctx, sha256, rootParentID)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// TotalSizeByRootParentID provides a mock function with given fields: ctx, id
+func (_m *GenericBlobRepository) TotalSizeByRootParentID(ctx context.Context, id int64) (int64, error) {
+ ret := _m.Called(ctx, id)
+
+ if len(ret) == 0 {
+ panic("no return value specified for TotalSizeByRootParentID")
+ }
+
+ var r0 int64
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64) (int64, error)); ok {
+ return rf(ctx, id)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64) int64); ok {
+ r0 = rf(ctx, id)
+ } else {
+ r0 = ret.Get(0).(int64)
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok {
+ r1 = rf(ctx, id)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// NewGenericBlobRepository creates a new instance of GenericBlobRepository. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewGenericBlobRepository(t interface {
+ mock.TestingT
+ Cleanup(func())
+}) *GenericBlobRepository {
+ mock := &GenericBlobRepository{}
+ mock.Mock.Test(t)
+
+ t.Cleanup(func() { mock.AssertExpectations(t) })
+
+ return mock
+}
diff --git a/registry/app/api/controller/mocks/image_repository.go b/registry/app/api/controller/mocks/image_repository.go
new file mode 100644
index 000000000..f5edb5394
--- /dev/null
+++ b/registry/app/api/controller/mocks/image_repository.go
@@ -0,0 +1,322 @@
+// Code generated by mockery v2.53.3. DO NOT EDIT.
+
+package mocks
+
+import (
+ context "context"
+
+ types "github.com/harness/gitness/registry/types"
+
+ mock "github.com/stretchr/testify/mock"
+)
+
+// ImageRepository is an autogenerated mock type for the ImageRepository type
+type ImageRepository struct {
+ mock.Mock
+}
+
+// CountLabelsByParentIDAndRepo provides a mock function with given fields: ctx, parentID, repo, search
+func (_m *ImageRepository) CountLabelsByParentIDAndRepo(ctx context.Context, parentID int64, repo string, search string) (int64, error) {
+ ret := _m.Called(ctx, parentID, repo, search)
+
+ if len(ret) == 0 {
+ panic("no return value specified for CountLabelsByParentIDAndRepo")
+ }
+
+ var r0 int64
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string) (int64, error)); ok {
+ return rf(ctx, parentID, repo, search)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string) int64); ok {
+ r0 = rf(ctx, parentID, repo, search)
+ } else {
+ r0 = ret.Get(0).(int64)
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, string, string) error); ok {
+ r1 = rf(ctx, parentID, repo, search)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// CreateOrUpdate provides a mock function with given fields: ctx, image
+func (_m *ImageRepository) CreateOrUpdate(ctx context.Context, image *types.Image) error {
+ ret := _m.Called(ctx, image)
+
+ if len(ret) == 0 {
+ panic("no return value specified for CreateOrUpdate")
+ }
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, *types.Image) error); ok {
+ r0 = rf(ctx, image)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// DeleteBandwidthStatByRegistryID provides a mock function with given fields: ctx, registryID
+func (_m *ImageRepository) DeleteBandwidthStatByRegistryID(ctx context.Context, registryID int64) error {
+ ret := _m.Called(ctx, registryID)
+
+ if len(ret) == 0 {
+ panic("no return value specified for DeleteBandwidthStatByRegistryID")
+ }
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64) error); ok {
+ r0 = rf(ctx, registryID)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// DeleteByRegistryID provides a mock function with given fields: ctx, registryID
+func (_m *ImageRepository) DeleteByRegistryID(ctx context.Context, registryID int64) error {
+ ret := _m.Called(ctx, registryID)
+
+ if len(ret) == 0 {
+ panic("no return value specified for DeleteByRegistryID")
+ }
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64) error); ok {
+ r0 = rf(ctx, registryID)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// DeleteDownloadStatByRegistryID provides a mock function with given fields: ctx, registryID
+func (_m *ImageRepository) DeleteDownloadStatByRegistryID(ctx context.Context, registryID int64) error {
+ ret := _m.Called(ctx, registryID)
+
+ if len(ret) == 0 {
+ panic("no return value specified for DeleteDownloadStatByRegistryID")
+ }
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64) error); ok {
+ r0 = rf(ctx, registryID)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// Get provides a mock function with given fields: ctx, id
+func (_m *ImageRepository) Get(ctx context.Context, id int64) (*types.Image, error) {
+ ret := _m.Called(ctx, id)
+
+ if len(ret) == 0 {
+ panic("no return value specified for Get")
+ }
+
+ var r0 *types.Image
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64) (*types.Image, error)); ok {
+ return rf(ctx, id)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64) *types.Image); ok {
+ r0 = rf(ctx, id)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.Image)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok {
+ r1 = rf(ctx, id)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// GetByName provides a mock function with given fields: ctx, registryID, name
+func (_m *ImageRepository) GetByName(ctx context.Context, registryID int64, name string) (*types.Image, error) {
+ ret := _m.Called(ctx, registryID, name)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GetByName")
+ }
+
+ var r0 *types.Image
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string) (*types.Image, error)); ok {
+ return rf(ctx, registryID, name)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string) *types.Image); ok {
+ r0 = rf(ctx, registryID, name)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.Image)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, string) error); ok {
+ r1 = rf(ctx, registryID, name)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// GetByRepoAndName provides a mock function with given fields: ctx, parentID, repo, name
+func (_m *ImageRepository) GetByRepoAndName(ctx context.Context, parentID int64, repo string, name string) (*types.Image, error) {
+ ret := _m.Called(ctx, parentID, repo, name)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GetByRepoAndName")
+ }
+
+ var r0 *types.Image
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string) (*types.Image, error)); ok {
+ return rf(ctx, parentID, repo, name)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string) *types.Image); ok {
+ r0 = rf(ctx, parentID, repo, name)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.Image)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, string, string) error); ok {
+ r1 = rf(ctx, parentID, repo, name)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// GetLabelsByParentIDAndRepo provides a mock function with given fields: ctx, parentID, repo, limit, offset, search
+func (_m *ImageRepository) GetLabelsByParentIDAndRepo(ctx context.Context, parentID int64, repo string, limit int, offset int, search string) ([]string, error) {
+ ret := _m.Called(ctx, parentID, repo, limit, offset, search)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GetLabelsByParentIDAndRepo")
+ }
+
+ var r0 []string
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, int, int, string) ([]string, error)); ok {
+ return rf(ctx, parentID, repo, limit, offset, search)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, int, int, string) []string); ok {
+ r0 = rf(ctx, parentID, repo, limit, offset, search)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]string)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, string, int, int, string) error); ok {
+ r1 = rf(ctx, parentID, repo, limit, offset, search)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// Update provides a mock function with given fields: ctx, artifact
+func (_m *ImageRepository) Update(ctx context.Context, artifact *types.Image) error {
+ ret := _m.Called(ctx, artifact)
+
+ if len(ret) == 0 {
+ panic("no return value specified for Update")
+ }
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, *types.Image) error); ok {
+ r0 = rf(ctx, artifact)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// UpdateStatus provides a mock function with given fields: ctx, artifact
+func (_m *ImageRepository) UpdateStatus(ctx context.Context, artifact *types.Image) error {
+ ret := _m.Called(ctx, artifact)
+
+ if len(ret) == 0 {
+ panic("no return value specified for UpdateStatus")
+ }
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, *types.Image) error); ok {
+ r0 = rf(ctx, artifact)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// DeleteByImageNameAndRegID provides a mock function with given fields: ctx, regID, image
+func (_m *ImageRepository) DeleteByImageNameAndRegID(ctx context.Context, regID int64, image string) error {
+ ret := _m.Called(ctx, regID, image)
+
+ if len(ret) == 0 {
+ panic("no return value specified for DeleteByImageNameAndRegID")
+ }
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string) error); ok {
+ r0 = rf(ctx, regID, image)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// DeleteByImageNameIfNoLinkedArtifacts provides a mock function with given fields: ctx, regID, image
+func (_m *ImageRepository) DeleteByImageNameIfNoLinkedArtifacts(ctx context.Context, regID int64, image string) error {
+ ret := _m.Called(ctx, regID, image)
+
+ if len(ret) == 0 {
+ panic("no return value specified for DeleteByImageNameIfNoLinkedArtifacts")
+ }
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string) error); ok {
+ r0 = rf(ctx, regID, image)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// NewImageRepository creates a new instance of ImageRepository. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewImageRepository(t interface {
+ mock.TestingT
+ Cleanup(func())
+}) *ImageRepository {
+ mock := &ImageRepository{}
+ mock.Mock.Test(t)
+
+ t.Cleanup(func() { mock.AssertExpectations(t) })
+
+ return mock
+}
diff --git a/registry/app/api/controller/mocks/image_store.go b/registry/app/api/controller/mocks/image_store.go
new file mode 100644
index 000000000..0729abc3a
--- /dev/null
+++ b/registry/app/api/controller/mocks/image_store.go
@@ -0,0 +1,211 @@
+package mocks
+
+import (
+ "context"
+
+ "github.com/harness/gitness/registry/types"
+
+ "github.com/stretchr/testify/mock"
+)
+
+// ImageStore is an autogenerated mock type for the ImageStore type
+type ImageStore struct {
+ mock.Mock
+}
+
+// Get provides a mock function with given fields: ctx, id
+func (m *ImageStore) Get(ctx context.Context, id int64) (*types.Image, error) {
+ ret := m.Called(ctx, id)
+
+ var r0 *types.Image
+ if rf, ok := ret.Get(0).(func(context.Context, int64) *types.Image); ok {
+ r0 = rf(ctx, id)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.Image)
+ }
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok {
+ r1 = rf(ctx, id)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// GetByName provides a mock function with given fields: ctx, registryID, name
+func (m *ImageStore) GetByName(ctx context.Context, registryID int64, name string) (*types.Image, error) {
+ ret := m.Called(ctx, registryID, name)
+
+ var r0 *types.Image
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string) *types.Image); ok {
+ r0 = rf(ctx, registryID, name)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.Image)
+ }
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context, int64, string) error); ok {
+ r1 = rf(ctx, registryID, name)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// GetLabelsByParentIDAndRepo provides a mock function with given fields: ctx, parentID, repo, limit, offset, search
+func (m *ImageStore) GetLabelsByParentIDAndRepo(ctx context.Context, parentID int64, repo string, limit int, offset int, search string) ([]string, error) {
+ ret := m.Called(ctx, parentID, repo, limit, offset, search)
+
+ var r0 []string
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, int, int, string) []string); ok {
+ r0 = rf(ctx, parentID, repo, limit, offset, search)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]string)
+ }
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context, int64, string, int, int, string) error); ok {
+ r1 = rf(ctx, parentID, repo, limit, offset, search)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// CountLabelsByParentIDAndRepo provides a mock function with given fields: ctx, parentID, repo, search
+func (m *ImageStore) CountLabelsByParentIDAndRepo(ctx context.Context, parentID int64, repo string, search string) (int64, error) {
+ ret := m.Called(ctx, parentID, repo, search)
+
+ var r0 int64
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string) int64); ok {
+ r0 = rf(ctx, parentID, repo, search)
+ } else {
+ r0 = ret.Get(0).(int64)
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context, int64, string, string) error); ok {
+ r1 = rf(ctx, parentID, repo, search)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// GetByRepoAndName provides a mock function with given fields: ctx, parentID, repo, name
+func (m *ImageStore) GetByRepoAndName(ctx context.Context, parentID int64, repo string, name string) (*types.Image, error) {
+ ret := m.Called(ctx, parentID, repo, name)
+
+ var r0 *types.Image
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string) *types.Image); ok {
+ r0 = rf(ctx, parentID, repo, name)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.Image)
+ }
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context, int64, string, string) error); ok {
+ r1 = rf(ctx, parentID, repo, name)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// CreateOrUpdate provides a mock function with given fields: ctx, image
+func (m *ImageStore) CreateOrUpdate(ctx context.Context, image *types.Image) error {
+ ret := m.Called(ctx, image)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, *types.Image) error); ok {
+ r0 = rf(ctx, image)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// Update provides a mock function with given fields: ctx, image
+func (m *ImageStore) Update(ctx context.Context, image *types.Image) error {
+ ret := m.Called(ctx, image)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, *types.Image) error); ok {
+ r0 = rf(ctx, image)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// UpdateStatus provides a mock function with given fields: ctx, image
+func (m *ImageStore) UpdateStatus(ctx context.Context, image *types.Image) error {
+ ret := m.Called(ctx, image)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, *types.Image) error); ok {
+ r0 = rf(ctx, image)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// DeleteByRegistryID provides a mock function with given fields: ctx, registryID
+func (m *ImageStore) DeleteByRegistryID(ctx context.Context, registryID int64) error {
+ ret := m.Called(ctx, registryID)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64) error); ok {
+ r0 = rf(ctx, registryID)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// DeleteBandwidthStatByRegistryID provides a mock function with given fields: ctx, registryID
+func (m *ImageStore) DeleteBandwidthStatByRegistryID(ctx context.Context, registryID int64) error {
+ ret := m.Called(ctx, registryID)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64) error); ok {
+ r0 = rf(ctx, registryID)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// DeleteDownloadStatByRegistryID provides a mock function with given fields: ctx, registryID
+func (m *ImageStore) DeleteDownloadStatByRegistryID(ctx context.Context, registryID int64) error {
+ ret := m.Called(ctx, registryID)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64) error); ok {
+ r0 = rf(ctx, registryID)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
diff --git a/registry/app/api/controller/mocks/manifest_repository.go b/registry/app/api/controller/mocks/manifest_repository.go
new file mode 100644
index 000000000..d50fc523a
--- /dev/null
+++ b/registry/app/api/controller/mocks/manifest_repository.go
@@ -0,0 +1,477 @@
+// Code generated by mockery v2.53.3. DO NOT EDIT.
+
+package mocks
+
+import (
+ context "context"
+
+ types "github.com/harness/gitness/registry/types"
+
+ digest "github.com/opencontainers/go-digest"
+ mock "github.com/stretchr/testify/mock"
+)
+
+// ManifestRepository is an autogenerated mock type for the ManifestRepository type
+type ManifestRepository struct {
+ mock.Mock
+}
+
+// AssociateLayerBlob provides a mock function with given fields: ctx, m, b
+func (_m *ManifestRepository) AssociateLayerBlob(ctx context.Context, m *types.Manifest, b *types.Blob) error {
+ ret := _m.Called(ctx, m, b)
+
+ if len(ret) == 0 {
+ panic("no return value specified for AssociateLayerBlob")
+ }
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, *types.Manifest, *types.Blob) error); ok {
+ r0 = rf(ctx, m, b)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// Count provides a mock function with given fields: ctx
+func (_m *ManifestRepository) Count(ctx context.Context) (int, error) {
+ ret := _m.Called(ctx)
+
+ if len(ret) == 0 {
+ panic("no return value specified for Count")
+ }
+
+ var r0 int
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context) (int, error)); ok {
+ return rf(ctx)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context) int); ok {
+ r0 = rf(ctx)
+ } else {
+ r0 = ret.Get(0).(int)
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context) error); ok {
+ r1 = rf(ctx)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// Create provides a mock function with given fields: ctx, m
+func (_m *ManifestRepository) Create(ctx context.Context, m *types.Manifest) error {
+ ret := _m.Called(ctx, m)
+
+ if len(ret) == 0 {
+ panic("no return value specified for Create")
+ }
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, *types.Manifest) error); ok {
+ r0 = rf(ctx, m)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// CreateOrFind provides a mock function with given fields: ctx, m
+func (_m *ManifestRepository) CreateOrFind(ctx context.Context, m *types.Manifest) error {
+ ret := _m.Called(ctx, m)
+
+ if len(ret) == 0 {
+ panic("no return value specified for CreateOrFind")
+ }
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, *types.Manifest) error); ok {
+ r0 = rf(ctx, m)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// Delete provides a mock function with given fields: ctx, registryID, id
+func (_m *ManifestRepository) Delete(ctx context.Context, registryID int64, id int64) error {
+ ret := _m.Called(ctx, registryID, id)
+
+ if len(ret) == 0 {
+ panic("no return value specified for Delete")
+ }
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, int64) error); ok {
+ r0 = rf(ctx, registryID, id)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// DeleteManifest provides a mock function with given fields: ctx, repoID, imageName, d
+func (_m *ManifestRepository) DeleteManifest(ctx context.Context, repoID int64, imageName string, d digest.Digest) (bool, error) {
+ ret := _m.Called(ctx, repoID, imageName, d)
+
+ if len(ret) == 0 {
+ panic("no return value specified for DeleteManifest")
+ }
+
+ var r0 bool
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, digest.Digest) (bool, error)); ok {
+ return rf(ctx, repoID, imageName, d)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, digest.Digest) bool); ok {
+ r0 = rf(ctx, repoID, imageName, d)
+ } else {
+ r0 = ret.Get(0).(bool)
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, string, digest.Digest) error); ok {
+ r1 = rf(ctx, repoID, imageName, d)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// DissociateLayerBlob provides a mock function with given fields: ctx, m, b
+func (_m *ManifestRepository) DissociateLayerBlob(ctx context.Context, m *types.Manifest, b *types.Blob) error {
+ ret := _m.Called(ctx, m, b)
+
+ if len(ret) == 0 {
+ panic("no return value specified for DissociateLayerBlob")
+ }
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, *types.Manifest, *types.Blob) error); ok {
+ r0 = rf(ctx, m, b)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// FindAll provides a mock function with given fields: ctx
+func (_m *ManifestRepository) FindAll(ctx context.Context) (types.Manifests, error) {
+ ret := _m.Called(ctx)
+
+ if len(ret) == 0 {
+ panic("no return value specified for FindAll")
+ }
+
+ var r0 types.Manifests
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context) (types.Manifests, error)); ok {
+ return rf(ctx)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context) types.Manifests); ok {
+ r0 = rf(ctx)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(types.Manifests)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context) error); ok {
+ r1 = rf(ctx)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// FindManifestByDigest provides a mock function with given fields: ctx, repoID, imageName, _a3
+func (_m *ManifestRepository) FindManifestByDigest(ctx context.Context, repoID int64, imageName string, _a3 types.Digest) (*types.Manifest, error) {
+ ret := _m.Called(ctx, repoID, imageName, _a3)
+
+ if len(ret) == 0 {
+ panic("no return value specified for FindManifestByDigest")
+ }
+
+ var r0 *types.Manifest
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, types.Digest) (*types.Manifest, error)); ok {
+ return rf(ctx, repoID, imageName, _a3)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, types.Digest) *types.Manifest); ok {
+ r0 = rf(ctx, repoID, imageName, _a3)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.Manifest)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, string, types.Digest) error); ok {
+ r1 = rf(ctx, repoID, imageName, _a3)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// FindManifestByTagName provides a mock function with given fields: ctx, repoID, imageName, tag
+func (_m *ManifestRepository) FindManifestByTagName(ctx context.Context, repoID int64, imageName string, tag string) (*types.Manifest, error) {
+ ret := _m.Called(ctx, repoID, imageName, tag)
+
+ if len(ret) == 0 {
+ panic("no return value specified for FindManifestByTagName")
+ }
+
+ var r0 *types.Manifest
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string) (*types.Manifest, error)); ok {
+ return rf(ctx, repoID, imageName, tag)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string) *types.Manifest); ok {
+ r0 = rf(ctx, repoID, imageName, tag)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.Manifest)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, string, string) error); ok {
+ r1 = rf(ctx, repoID, imageName, tag)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// FindManifestPayloadByTagName provides a mock function with given fields: ctx, parentID, repoKey, imageName, version
+func (_m *ManifestRepository) FindManifestPayloadByTagName(ctx context.Context, parentID int64, repoKey string, imageName string, version string) (*types.Payload, error) {
+ ret := _m.Called(ctx, parentID, repoKey, imageName, version)
+
+ if len(ret) == 0 {
+ panic("no return value specified for FindManifestPayloadByTagName")
+ }
+
+ var r0 *types.Payload
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string, string) (*types.Payload, error)); ok {
+ return rf(ctx, parentID, repoKey, imageName, version)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string, string) *types.Payload); ok {
+ r0 = rf(ctx, parentID, repoKey, imageName, version)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.Payload)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, string, string, string) error); ok {
+ r1 = rf(ctx, parentID, repoKey, imageName, version)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// Get provides a mock function with given fields: ctx, manifestID
+func (_m *ManifestRepository) Get(ctx context.Context, manifestID int64) (*types.Manifest, error) {
+ ret := _m.Called(ctx, manifestID)
+
+ if len(ret) == 0 {
+ panic("no return value specified for Get")
+ }
+
+ var r0 *types.Manifest
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64) (*types.Manifest, error)); ok {
+ return rf(ctx, manifestID)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64) *types.Manifest); ok {
+ r0 = rf(ctx, manifestID)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.Manifest)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok {
+ r1 = rf(ctx, manifestID)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// GetManifestPayload provides a mock function with given fields: ctx, parentID, repoKey, imageName, _a4
+func (_m *ManifestRepository) GetManifestPayload(ctx context.Context, parentID int64, repoKey string, imageName string, _a4 types.Digest) (*types.Payload, error) {
+ ret := _m.Called(ctx, parentID, repoKey, imageName, _a4)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GetManifestPayload")
+ }
+
+ var r0 *types.Payload
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string, types.Digest) (*types.Payload, error)); ok {
+ return rf(ctx, parentID, repoKey, imageName, _a4)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string, types.Digest) *types.Payload); ok {
+ r0 = rf(ctx, parentID, repoKey, imageName, _a4)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.Payload)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, string, string, types.Digest) error); ok {
+ r1 = rf(ctx, parentID, repoKey, imageName, _a4)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// LayerBlobs provides a mock function with given fields: ctx, m
+func (_m *ManifestRepository) LayerBlobs(ctx context.Context, m *types.Manifest) (types.Blobs, error) {
+ ret := _m.Called(ctx, m)
+
+ if len(ret) == 0 {
+ panic("no return value specified for LayerBlobs")
+ }
+
+ var r0 types.Blobs
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, *types.Manifest) (types.Blobs, error)); ok {
+ return rf(ctx, m)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, *types.Manifest) types.Blobs); ok {
+ r0 = rf(ctx, m)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(types.Blobs)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, *types.Manifest) error); ok {
+ r1 = rf(ctx, m)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// ListManifestsBySubject provides a mock function with given fields: ctx, repoID, id
+func (_m *ManifestRepository) ListManifestsBySubject(ctx context.Context, repoID int64, id int64) (types.Manifests, error) {
+ ret := _m.Called(ctx, repoID, id)
+
+ if len(ret) == 0 {
+ panic("no return value specified for ListManifestsBySubject")
+ }
+
+ var r0 types.Manifests
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, int64) (types.Manifests, error)); ok {
+ return rf(ctx, repoID, id)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, int64) types.Manifests); ok {
+ r0 = rf(ctx, repoID, id)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(types.Manifests)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, int64) error); ok {
+ r1 = rf(ctx, repoID, id)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// ListManifestsBySubjectDigest provides a mock function with given fields: ctx, repoID, _a2
+func (_m *ManifestRepository) ListManifestsBySubjectDigest(ctx context.Context, repoID int64, _a2 types.Digest) (types.Manifests, error) {
+ ret := _m.Called(ctx, repoID, _a2)
+
+ if len(ret) == 0 {
+ panic("no return value specified for ListManifestsBySubjectDigest")
+ }
+
+ var r0 types.Manifests
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, types.Digest) (types.Manifests, error)); ok {
+ return rf(ctx, repoID, _a2)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, types.Digest) types.Manifests); ok {
+ r0 = rf(ctx, repoID, _a2)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(types.Manifests)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, types.Digest) error); ok {
+ r1 = rf(ctx, repoID, _a2)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// References provides a mock function with given fields: ctx, m
+func (_m *ManifestRepository) References(ctx context.Context, m *types.Manifest) (types.Manifests, error) {
+ ret := _m.Called(ctx, m)
+
+ if len(ret) == 0 {
+ panic("no return value specified for References")
+ }
+
+ var r0 types.Manifests
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, *types.Manifest) (types.Manifests, error)); ok {
+ return rf(ctx, m)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, *types.Manifest) types.Manifests); ok {
+ r0 = rf(ctx, m)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(types.Manifests)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, *types.Manifest) error); ok {
+ r1 = rf(ctx, m)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// NewManifestRepository creates a new instance of ManifestRepository. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewManifestRepository(t interface {
+ mock.TestingT
+ Cleanup(func())
+}) *ManifestRepository {
+ mock := &ManifestRepository{}
+ mock.Mock.Test(t)
+
+ t.Cleanup(func() { mock.AssertExpectations(t) })
+
+ return mock
+}
diff --git a/registry/app/api/controller/mocks/registry_metadata_helper.go b/registry/app/api/controller/mocks/registry_metadata_helper.go
new file mode 100644
index 000000000..89acfaa6d
--- /dev/null
+++ b/registry/app/api/controller/mocks/registry_metadata_helper.go
@@ -0,0 +1,381 @@
+//go:generate mockery --name RegistryMetadataHelper --output . --filename registry_metadata_helper.go --outpkg mocks --with-expecter
+
+package mocks
+
+import (
+ "context"
+
+ api "github.com/harness/gitness/registry/app/api/openapi/contracts/artifact"
+ registrytypes "github.com/harness/gitness/registry/types"
+ "github.com/harness/gitness/types"
+ "github.com/harness/gitness/types/enum"
+
+ "github.com/stretchr/testify/mock"
+)
+
+// RegistryMetadataHelper is an autogenerated mock type for the RegistryMetadataHelper type
+type RegistryMetadataHelper struct {
+ mock.Mock
+}
+
+// GetPermissionChecks provides a mock function with given fields: space, registryIdentifier, permission
+func (_m *RegistryMetadataHelper) GetPermissionChecks(space *types.SpaceCore, registryIdentifier string, permission enum.Permission) []types.PermissionCheck {
+ ret := _m.Called(space, registryIdentifier, permission)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GetPermissionChecks")
+ }
+
+ var r0 []types.PermissionCheck
+ if rf, ok := ret.Get(0).(func(*types.SpaceCore, string, enum.Permission) []types.PermissionCheck); ok {
+ r0 = rf(space, registryIdentifier, permission)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]types.PermissionCheck)
+ }
+ }
+
+ return r0
+}
+
+// GetRegistryMetadata provides a mock function with given fields: ctx, registryID
+func (_m *RegistryMetadataHelper) GetRegistryMetadata(ctx context.Context, registryID int64) (*registrytypes.Registry, error) {
+ ret := _m.Called(ctx, registryID)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GetRegistryMetadata")
+ }
+
+ var r0 *registrytypes.Registry
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64) (*registrytypes.Registry, error)); ok {
+ return rf(ctx, registryID)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64) *registrytypes.Registry); ok {
+ r0 = rf(ctx, registryID)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*registrytypes.Registry)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok {
+ r1 = rf(ctx, registryID)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// GetRegistryMetadataByIdentifier provides a mock function with given fields: ctx, identifier
+func (_m *RegistryMetadataHelper) GetRegistryMetadataByIdentifier(ctx context.Context, identifier string) (*registrytypes.Registry, error) {
+ ret := _m.Called(ctx, identifier)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GetRegistryMetadataByIdentifier")
+ }
+
+ var r0 *registrytypes.Registry
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, string) (*registrytypes.Registry, error)); ok {
+ return rf(ctx, identifier)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, string) *registrytypes.Registry); ok {
+ r0 = rf(ctx, identifier)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*registrytypes.Registry)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
+ r1 = rf(ctx, identifier)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// GetRegistryMetadataByParentIDAndIdentifier provides a mock function with given fields: ctx, parentID, identifier
+func (_m *RegistryMetadataHelper) GetRegistryMetadataByParentIDAndIdentifier(ctx context.Context, parentID int64, identifier string) (*registrytypes.Registry, error) {
+ ret := _m.Called(ctx, parentID, identifier)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GetRegistryMetadataByParentIDAndIdentifier")
+ }
+
+ var r0 *registrytypes.Registry
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string) (*registrytypes.Registry, error)); ok {
+ return rf(ctx, parentID, identifier)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string) *registrytypes.Registry); ok {
+ r0 = rf(ctx, parentID, identifier)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*registrytypes.Registry)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, string) error); ok {
+ r1 = rf(ctx, parentID, identifier)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// GetRegistryMetadataByParentPathAndIdentifier provides a mock function with given fields: ctx, parentPath, identifier
+func (_m *RegistryMetadataHelper) GetRegistryMetadataByParentPathAndIdentifier(ctx context.Context, parentPath string, identifier string) (*registrytypes.Registry, error) {
+ ret := _m.Called(ctx, parentPath, identifier)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GetRegistryMetadataByParentPathAndIdentifier")
+ }
+
+ var r0 *registrytypes.Registry
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, string, string) (*registrytypes.Registry, error)); ok {
+ return rf(ctx, parentPath, identifier)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, string, string) *registrytypes.Registry); ok {
+ r0 = rf(ctx, parentPath, identifier)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*registrytypes.Registry)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok {
+ r1 = rf(ctx, parentPath, identifier)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// GetRegistryMetadataByPath provides a mock function with given fields: ctx, path
+func (_m *RegistryMetadataHelper) GetRegistryMetadataByPath(ctx context.Context, path string) (*registrytypes.Registry, error) {
+ ret := _m.Called(ctx, path)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GetRegistryMetadataByPath")
+ }
+
+ var r0 *registrytypes.Registry
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, string) (*registrytypes.Registry, error)); ok {
+ return rf(ctx, path)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, string) *registrytypes.Registry); ok {
+ r0 = rf(ctx, path)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*registrytypes.Registry)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
+ r1 = rf(ctx, path)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// GetRegistryRequestBaseInfo provides a mock function with given fields: ctx, parentPath, identifier
+func (_m *RegistryMetadataHelper) GetRegistryRequestBaseInfo(ctx context.Context, parentPath string, identifier string) (*registrytypes.RegistryRequestBaseInfo, error) {
+ ret := _m.Called(ctx, parentPath, identifier)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GetRegistryRequestBaseInfo")
+ }
+
+ var r0 *registrytypes.RegistryRequestBaseInfo
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, string, string) (*registrytypes.RegistryRequestBaseInfo, error)); ok {
+ return rf(ctx, parentPath, identifier)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, string, string) *registrytypes.RegistryRequestBaseInfo); ok {
+ r0 = rf(ctx, parentPath, identifier)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*registrytypes.RegistryRequestBaseInfo)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok {
+ r1 = rf(ctx, parentPath, identifier)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// GetSecretSpaceID provides a mock function with given fields: ctx, secretSpacePath
+func (_m *RegistryMetadataHelper) GetSecretSpaceID(ctx context.Context, secretSpacePath *string) (int64, error) {
+ ret := _m.Called(ctx, secretSpacePath)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GetSecretSpaceID")
+ }
+
+ var r0 int64
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, *string) (int64, error)); ok {
+ return rf(ctx, secretSpacePath)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, *string) int64); ok {
+ r0 = rf(ctx, secretSpacePath)
+ } else {
+ r0 = ret.Get(0).(int64)
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, *string) error); ok {
+ r1 = rf(ctx, secretSpacePath)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// MapToAPIExtraHeaders provides a mock function with given fields: headers
+func (_m *RegistryMetadataHelper) MapToAPIExtraHeaders(headers []types.ExtraHeader) []api.ExtraHeader {
+ ret := _m.Called(headers)
+
+ if len(ret) == 0 {
+ panic("no return value specified for MapToAPIExtraHeaders")
+ }
+
+ var r0 []api.ExtraHeader
+ if rf, ok := ret.Get(0).(func([]types.ExtraHeader) []api.ExtraHeader); ok {
+ r0 = rf(headers)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]api.ExtraHeader)
+ }
+ }
+
+ return r0
+}
+
+// MapToAPIWebhookTriggers provides a mock function with given fields: triggers
+func (_m *RegistryMetadataHelper) MapToAPIWebhookTriggers(triggers []enum.WebhookTrigger) []api.Trigger {
+ ret := _m.Called(triggers)
+
+ if len(ret) == 0 {
+ panic("no return value specified for MapToAPIWebhookTriggers")
+ }
+
+ var r0 []api.Trigger
+ if rf, ok := ret.Get(0).(func([]enum.WebhookTrigger) []api.Trigger); ok {
+ r0 = rf(triggers)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]api.Trigger)
+ }
+ }
+
+ return r0
+}
+
+// MapToInternalWebhookTriggers provides a mock function with given fields: triggers
+func (_m *RegistryMetadataHelper) MapToInternalWebhookTriggers(triggers []api.Trigger) []enum.WebhookTrigger {
+ ret := _m.Called(triggers)
+
+ if len(ret) == 0 {
+ panic("no return value specified for MapToInternalWebhookTriggers")
+ }
+
+ var r0 []enum.WebhookTrigger
+ if rf, ok := ret.Get(0).(func([]api.Trigger) []enum.WebhookTrigger); ok {
+ r0 = rf(triggers)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]enum.WebhookTrigger)
+ }
+ }
+
+ return r0
+}
+
+// MapToWebhookCore provides a mock function with given fields: ctx, webhookRequest, regInfo
+func (_m *RegistryMetadataHelper) MapToWebhookCore(ctx context.Context, webhookRequest api.WebhookRequest, regInfo *registrytypes.RegistryRequestBaseInfo) (*types.WebhookCore, error) {
+ ret := _m.Called(ctx, webhookRequest, regInfo)
+
+ if len(ret) == 0 {
+ panic("no return value specified for MapToWebhookCore")
+ }
+
+ var r0 *types.WebhookCore
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, api.WebhookRequest, *registrytypes.RegistryRequestBaseInfo) (*types.WebhookCore, error)); ok {
+ return rf(ctx, webhookRequest, regInfo)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, api.WebhookRequest, *registrytypes.RegistryRequestBaseInfo) *types.WebhookCore); ok {
+ r0 = rf(ctx, webhookRequest, regInfo)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.WebhookCore)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, api.WebhookRequest, *registrytypes.RegistryRequestBaseInfo) error); ok {
+ r1 = rf(ctx, webhookRequest, regInfo)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// MapToWebhookResponseEntity provides a mock function with given fields: ctx, webhook
+func (_m *RegistryMetadataHelper) MapToWebhookResponseEntity(ctx context.Context, webhook *types.WebhookCore) (*api.Webhook, error) {
+ ret := _m.Called(ctx, webhook)
+
+ if len(ret) == 0 {
+ panic("no return value specified for MapToWebhookResponseEntity")
+ }
+
+ var r0 *api.Webhook
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, *types.WebhookCore) (*api.Webhook, error)); ok {
+ return rf(ctx, webhook)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, *types.WebhookCore) *api.Webhook); ok {
+ r0 = rf(ctx, webhook)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*api.Webhook)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, *types.WebhookCore) error); ok {
+ r1 = rf(ctx, webhook)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// NewRegistryMetadataHelper creates a new instance of RegistryMetadataHelper. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewRegistryMetadataHelper(t interface {
+ mock.TestingT
+ Cleanup(func())
+}) *RegistryMetadataHelper {
+ mock := &RegistryMetadataHelper{}
+ mock.Mock.Test(t)
+
+ t.Cleanup(func() { mock.AssertExpectations(t) })
+
+ return mock
+}
diff --git a/registry/app/api/controller/mocks/registry_repository.go b/registry/app/api/controller/mocks/registry_repository.go
new file mode 100644
index 000000000..172df3d99
--- /dev/null
+++ b/registry/app/api/controller/mocks/registry_repository.go
@@ -0,0 +1,292 @@
+// Code generated by testify. DO NOT EDIT.
+
+package mocks
+
+import (
+ "context"
+
+ "github.com/harness/gitness/registry/app/store"
+ "github.com/harness/gitness/registry/types"
+
+ "github.com/stretchr/testify/mock"
+)
+
+// FetchUpstreamProxyIDs provides a mock function
+func (m *RegistryRepository) FetchUpstreamProxyIDs(ctx context.Context, repokeys []string, parentID int64) ([]int64, error) {
+ ret := m.Called(ctx, repokeys, parentID)
+
+ var r0 []int64
+ if rf, ok := ret.Get(0).(func(context.Context, []string, int64) []int64); ok {
+ r0 = rf(ctx, repokeys, parentID)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]int64)
+ }
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context, []string, int64) error); ok {
+ r1 = rf(ctx, repokeys, parentID)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// RegistryRepository is a mock of RegistryRepository interface.
+type RegistryRepository struct {
+ mock.Mock
+}
+
+// GetAll provides a mock function
+func (m *RegistryRepository) GetAll(ctx context.Context, parentID int64, packageTypes []string, sortByField string, sortByOrder string, limit int, offset int, search string, repoType string, recursive bool) (*[]store.RegistryMetadata, error) {
+ ret := m.Called(ctx, parentID, packageTypes, sortByField, sortByOrder, limit, offset, search, repoType, recursive)
+
+ var r0 *[]store.RegistryMetadata
+ if rf, ok := ret.Get(0).(func(context.Context, int64, []string, string, string, int, int, string, string, bool) *[]store.RegistryMetadata); ok {
+ r0 = rf(ctx, parentID, packageTypes, sortByField, sortByOrder, limit, offset, search, repoType, recursive)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*[]store.RegistryMetadata)
+ }
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context, int64, []string, string, string, int, int, string, string, bool) error); ok {
+ r1 = rf(ctx, parentID, packageTypes, sortByField, sortByOrder, limit, offset, search, repoType, recursive)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// FetchUpstreamProxyKeys provides a mock function
+func (m *RegistryRepository) FetchUpstreamProxyKeys(ctx context.Context, ids []int64) ([]string, error) {
+ ret := m.Called(ctx, ids)
+
+ var r0 []string
+ if rf, ok := ret.Get(0).(func(context.Context, []int64) []string); ok {
+ r0 = rf(ctx, ids)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]string)
+ }
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context, []int64) error); ok {
+ r1 = rf(ctx, ids)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// Get provides a mock function
+func (m *RegistryRepository) Get(ctx context.Context, id int64) (*types.Registry, error) {
+ ret := m.Called(ctx, id)
+
+ var r0 *types.Registry
+ if rf, ok := ret.Get(0).(func(context.Context, int64) *types.Registry); ok {
+ r0 = rf(ctx, id)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.Registry)
+ }
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok {
+ r1 = rf(ctx, id)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// GetByIDIn provides a mock function
+func (m *RegistryRepository) GetByIDIn(ctx context.Context, ids []int64) (*[]types.Registry, error) {
+ ret := m.Called(ctx, ids)
+
+ var r0 *[]types.Registry
+ if rf, ok := ret.Get(0).(func(context.Context, []int64) *[]types.Registry); ok {
+ r0 = rf(ctx, ids)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*[]types.Registry)
+ }
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context, []int64) error); ok {
+ r1 = rf(ctx, ids)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// GetByParentIDAndName provides a mock function
+func (m *RegistryRepository) GetByParentIDAndName(ctx context.Context, parentID int64, name string) (*types.Registry, error) {
+ ret := m.Called(ctx, parentID, name)
+
+ var r0 *types.Registry
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string) *types.Registry); ok {
+ r0 = rf(ctx, parentID, name)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.Registry)
+ }
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context, int64, string) error); ok {
+ r1 = rf(ctx, parentID, name)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// GetByRootParentIDAndName provides a mock function
+func (m *RegistryRepository) GetByRootParentIDAndName(ctx context.Context, parentID int64, name string) (*types.Registry, error) {
+ ret := m.Called(ctx, parentID, name)
+
+ var r0 *types.Registry
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string) *types.Registry); ok {
+ r0 = rf(ctx, parentID, name)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.Registry)
+ }
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context, int64, string) error); ok {
+ r1 = rf(ctx, parentID, name)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// Create provides a mock function
+func (m *RegistryRepository) Create(ctx context.Context, registry *types.Registry) (int64, error) {
+ ret := m.Called(ctx, registry)
+
+ var r0 int64
+ if rf, ok := ret.Get(0).(func(context.Context, *types.Registry) int64); ok {
+ r0 = rf(ctx, registry)
+ } else {
+ r0 = ret.Get(0).(int64)
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context, *types.Registry) error); ok {
+ r1 = rf(ctx, registry)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// Delete provides a mock function
+func (m *RegistryRepository) Delete(ctx context.Context, parentID int64, name string) error {
+ ret := m.Called(ctx, parentID, name)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string) error); ok {
+ r0 = rf(ctx, parentID, name)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// Update provides a mock function
+func (m *RegistryRepository) Update(ctx context.Context, registry *types.Registry) error {
+ ret := m.Called(ctx, registry)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, *types.Registry) error); ok {
+ r0 = rf(ctx, registry)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// CountAll provides a mock function
+func (m *RegistryRepository) CountAll(ctx context.Context, parentID int64, packageTypes []string, search string, repoType string) (int64, error) {
+ ret := m.Called(ctx, parentID, packageTypes, search, repoType)
+
+ var r0 int64
+ if rf, ok := ret.Get(0).(func(context.Context, int64, []string, string, string) int64); ok {
+ r0 = rf(ctx, parentID, packageTypes, search, repoType)
+ } else {
+ r0 = ret.Get(0).(int64)
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context, int64, []string, string, string) error); ok {
+ r1 = rf(ctx, parentID, packageTypes, search, repoType)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// Count provides a mock function
+func (m *RegistryRepository) Count(ctx context.Context) (int64, error) {
+ ret := m.Called(ctx)
+
+ var r0 int64
+ if rf, ok := ret.Get(0).(func(context.Context) int64); ok {
+ r0 = rf(ctx)
+ } else {
+ r0 = ret.Get(0).(int64)
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context) error); ok {
+ r1 = rf(ctx)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// FetchRegistriesIDByUpstreamProxyID provides a mock function
+func (m *RegistryRepository) FetchRegistriesIDByUpstreamProxyID(ctx context.Context, upstreamProxyID string, rootParentID int64) ([]int64, error) {
+ ret := m.Called(ctx, upstreamProxyID, rootParentID)
+
+ var r0 []int64
+ if rf, ok := ret.Get(0).(func(context.Context, string, int64) []int64); ok {
+ r0 = rf(ctx, upstreamProxyID, rootParentID)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]int64)
+ }
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context, string, int64) error); ok {
+ r1 = rf(ctx, upstreamProxyID, rootParentID)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
diff --git a/registry/app/api/controller/mocks/reporter.go b/registry/app/api/controller/mocks/reporter.go
new file mode 100644
index 000000000..b81f5f543
--- /dev/null
+++ b/registry/app/api/controller/mocks/reporter.go
@@ -0,0 +1,34 @@
+package mocks
+
+import (
+ "context"
+
+ registryevents "github.com/harness/gitness/registry/app/events"
+
+ "github.com/stretchr/testify/mock"
+)
+
+// Reporter is a mock implementation of registryevents.Reporter
+type Reporter struct {
+ mock.Mock
+}
+
+func NewReporter() *Reporter {
+ return &Reporter{}
+}
+
+// Report provides a mock function
+func (m *Reporter) Report(ctx context.Context, event interface{}) error {
+ args := m.Called(ctx, event)
+ return args.Error(0)
+}
+
+// ArtifactCreated provides a mock function
+func (m *Reporter) ArtifactCreated(ctx context.Context, payload *registryevents.ArtifactCreatedPayload) {
+ m.Called(ctx, payload)
+}
+
+// ArtifactDeleted provides a mock function
+func (m *Reporter) ArtifactDeleted(ctx context.Context, payload *registryevents.ArtifactDeletedPayload) {
+ m.Called(ctx, payload)
+}
diff --git a/registry/app/api/controller/mocks/space_finder.go b/registry/app/api/controller/mocks/space_finder.go
new file mode 100644
index 000000000..ee18b039a
--- /dev/null
+++ b/registry/app/api/controller/mocks/space_finder.go
@@ -0,0 +1,130 @@
+// Code generated by testify. DO NOT EDIT.
+
+package mocks
+
+import (
+ "context"
+
+ "github.com/harness/gitness/types"
+
+ "github.com/stretchr/testify/mock"
+)
+
+// SpaceFinder is a mock of SpaceFinder interface.
+type SpaceFinder struct {
+ mock.Mock
+}
+
+// Find provides a mock function
+func (m *SpaceFinder) Find(ctx context.Context, id int64) (*types.SpaceCore, error) {
+ ret := m.Called(ctx, id)
+
+ var r0 *types.SpaceCore
+ if rf, ok := ret.Get(0).(func(context.Context, int64) *types.SpaceCore); ok {
+ r0 = rf(ctx, id)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.SpaceCore)
+ }
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok {
+ r1 = rf(ctx, id)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// FindByRef provides a mock function
+func (m *SpaceFinder) FindByID(ctx context.Context, id int64) (*types.SpaceCore, error) {
+ ret := m.Called(ctx, id)
+
+ var r0 *types.SpaceCore
+ if rf, ok := ret.Get(0).(func(context.Context, int64) *types.SpaceCore); ok {
+ r0 = rf(ctx, id)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.SpaceCore)
+ }
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok {
+ r1 = rf(ctx, id)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+func (m *SpaceFinder) FindByRef(ctx context.Context, ref string) (*types.SpaceCore, error) {
+ ret := m.Called(ctx, ref)
+
+ var r0 *types.SpaceCore
+ if rf, ok := ret.Get(0).(func(context.Context, string) *types.SpaceCore); ok {
+ r0 = rf(ctx, ref)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.SpaceCore)
+ }
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
+ r1 = rf(ctx, ref)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// FindByPath provides a mock function
+func (m *SpaceFinder) FindByPath(ctx context.Context, path string) (*types.SpaceCore, error) {
+ ret := m.Called(ctx, path)
+
+ var r0 *types.SpaceCore
+ if rf, ok := ret.Get(0).(func(context.Context, string) *types.SpaceCore); ok {
+ r0 = rf(ctx, path)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.SpaceCore)
+ }
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
+ r1 = rf(ctx, path)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// FindByIdentifier provides a mock function
+func (m *SpaceFinder) FindByIdentifier(ctx context.Context, identifier string) (*types.SpaceCore, error) {
+ ret := m.Called(ctx, identifier)
+
+ var r0 *types.SpaceCore
+ if rf, ok := ret.Get(0).(func(context.Context, string) *types.SpaceCore); ok {
+ r0 = rf(ctx, identifier)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.SpaceCore)
+ }
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
+ r1 = rf(ctx, identifier)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
diff --git a/registry/app/api/controller/mocks/space_path_store.go b/registry/app/api/controller/mocks/space_path_store.go
new file mode 100644
index 000000000..e8a307975
--- /dev/null
+++ b/registry/app/api/controller/mocks/space_path_store.go
@@ -0,0 +1,102 @@
+package mocks
+
+import (
+ "context"
+
+ "github.com/harness/gitness/types"
+
+ "github.com/stretchr/testify/mock"
+)
+
+// SpacePathStore is a mock of SpacePathStore interface.
+type SpacePathStore struct {
+ mock.Mock
+}
+
+// FindByPath provides a mock function
+func (m *SpacePathStore) FindByPath(ctx context.Context, path string) (*types.SpacePath, error) {
+ ret := m.Called(ctx, path)
+
+ var r0 *types.SpacePath
+ if rf, ok := ret.Get(0).(func(context.Context, string) *types.SpacePath); ok {
+ r0 = rf(ctx, path)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.SpacePath)
+ }
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
+ r1 = rf(ctx, path)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// FindPrimaryBySpaceID provides a mock function
+func (m *SpacePathStore) FindPrimaryBySpaceID(ctx context.Context, spaceID int64) (*types.SpacePath, error) {
+ ret := m.Called(ctx, spaceID)
+
+ var r0 *types.SpacePath
+ if rf, ok := ret.Get(0).(func(context.Context, int64) *types.SpacePath); ok {
+ r0 = rf(ctx, spaceID)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.SpacePath)
+ }
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok {
+ r1 = rf(ctx, spaceID)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// InsertSegment provides a mock function
+func (m *SpacePathStore) InsertSegment(ctx context.Context, segment *types.SpacePathSegment) error {
+ ret := m.Called(ctx, segment)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, *types.SpacePathSegment) error); ok {
+ r0 = rf(ctx, segment)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// DeletePrimarySegment provides a mock function
+func (m *SpacePathStore) DeletePrimarySegment(ctx context.Context, spaceID int64) error {
+ ret := m.Called(ctx, spaceID)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64) error); ok {
+ r0 = rf(ctx, spaceID)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// DeletePathsAndDescendandPaths provides a mock function
+func (m *SpacePathStore) DeletePathsAndDescendandPaths(ctx context.Context, spaceID int64) error {
+ ret := m.Called(ctx, spaceID)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64) error); ok {
+ r0 = rf(ctx, spaceID)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
diff --git a/registry/app/api/controller/mocks/storage_driver.go b/registry/app/api/controller/mocks/storage_driver.go
new file mode 100644
index 000000000..b21e66c9c
--- /dev/null
+++ b/registry/app/api/controller/mocks/storage_driver.go
@@ -0,0 +1,306 @@
+// Code generated by mockery v2.53.3. DO NOT EDIT.
+
+package mocks
+
+import (
+ context "context"
+ io "io"
+
+ driver "github.com/harness/gitness/registry/app/driver"
+
+ mock "github.com/stretchr/testify/mock"
+)
+
+// StorageDriver is an autogenerated mock type for the StorageDriver type
+type StorageDriver struct {
+ mock.Mock
+}
+
+// Delete provides a mock function with given fields: ctx, path
+func (_m *StorageDriver) Delete(ctx context.Context, path string) error {
+ ret := _m.Called(ctx, path)
+
+ if len(ret) == 0 {
+ panic("no return value specified for Delete")
+ }
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, string) error); ok {
+ r0 = rf(ctx, path)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// GetContent provides a mock function with given fields: ctx, path
+func (_m *StorageDriver) GetContent(ctx context.Context, path string) ([]byte, error) {
+ ret := _m.Called(ctx, path)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GetContent")
+ }
+
+ var r0 []byte
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, string) ([]byte, error)); ok {
+ return rf(ctx, path)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, string) []byte); ok {
+ r0 = rf(ctx, path)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]byte)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
+ r1 = rf(ctx, path)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// List provides a mock function with given fields: ctx, path
+func (_m *StorageDriver) List(ctx context.Context, path string) ([]string, error) {
+ ret := _m.Called(ctx, path)
+
+ if len(ret) == 0 {
+ panic("no return value specified for List")
+ }
+
+ var r0 []string
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, string) ([]string, error)); ok {
+ return rf(ctx, path)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, string) []string); ok {
+ r0 = rf(ctx, path)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]string)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
+ r1 = rf(ctx, path)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// Move provides a mock function with given fields: ctx, sourcePath, destPath
+func (_m *StorageDriver) Move(ctx context.Context, sourcePath string, destPath string) error {
+ ret := _m.Called(ctx, sourcePath, destPath)
+
+ if len(ret) == 0 {
+ panic("no return value specified for Move")
+ }
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, string, string) error); ok {
+ r0 = rf(ctx, sourcePath, destPath)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// Name provides a mock function with no fields
+func (_m *StorageDriver) Name() string {
+ ret := _m.Called()
+
+ if len(ret) == 0 {
+ panic("no return value specified for Name")
+ }
+
+ var r0 string
+ if rf, ok := ret.Get(0).(func() string); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ return r0
+}
+
+// PutContent provides a mock function with given fields: ctx, path, content
+func (_m *StorageDriver) PutContent(ctx context.Context, path string, content []byte) error {
+ ret := _m.Called(ctx, path, content)
+
+ if len(ret) == 0 {
+ panic("no return value specified for PutContent")
+ }
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, string, []byte) error); ok {
+ r0 = rf(ctx, path, content)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// Reader provides a mock function with given fields: ctx, path, offset
+func (_m *StorageDriver) Reader(ctx context.Context, path string, offset int64) (io.ReadCloser, error) {
+ ret := _m.Called(ctx, path, offset)
+
+ if len(ret) == 0 {
+ panic("no return value specified for Reader")
+ }
+
+ var r0 io.ReadCloser
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, string, int64) (io.ReadCloser, error)); ok {
+ return rf(ctx, path, offset)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, string, int64) io.ReadCloser); ok {
+ r0 = rf(ctx, path, offset)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(io.ReadCloser)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, string, int64) error); ok {
+ r1 = rf(ctx, path, offset)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// RedirectURL provides a mock function with given fields: ctx, method, path
+func (_m *StorageDriver) RedirectURL(ctx context.Context, method string, path string) (string, error) {
+ ret := _m.Called(ctx, method, path)
+
+ if len(ret) == 0 {
+ panic("no return value specified for RedirectURL")
+ }
+
+ var r0 string
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, string, string) (string, error)); ok {
+ return rf(ctx, method, path)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, string, string) string); ok {
+ r0 = rf(ctx, method, path)
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok {
+ r1 = rf(ctx, method, path)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// Stat provides a mock function with given fields: ctx, path
+func (_m *StorageDriver) Stat(ctx context.Context, path string) (driver.FileInfo, error) {
+ ret := _m.Called(ctx, path)
+
+ if len(ret) == 0 {
+ panic("no return value specified for Stat")
+ }
+
+ var r0 driver.FileInfo
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, string) (driver.FileInfo, error)); ok {
+ return rf(ctx, path)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, string) driver.FileInfo); ok {
+ r0 = rf(ctx, path)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(driver.FileInfo)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
+ r1 = rf(ctx, path)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// Walk provides a mock function with given fields: ctx, path, f, options
+func (_m *StorageDriver) Walk(ctx context.Context, path string, f driver.WalkFn, options ...func(*driver.WalkOptions)) error {
+ _va := make([]interface{}, len(options))
+ for _i := range options {
+ _va[_i] = options[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, ctx, path, f)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ if len(ret) == 0 {
+ panic("no return value specified for Walk")
+ }
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, string, driver.WalkFn, ...func(*driver.WalkOptions)) error); ok {
+ r0 = rf(ctx, path, f, options...)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// Writer provides a mock function with given fields: ctx, path, a
+func (_m *StorageDriver) Writer(ctx context.Context, path string, a bool) (driver.FileWriter, error) {
+ ret := _m.Called(ctx, path, a)
+
+ if len(ret) == 0 {
+ panic("no return value specified for Writer")
+ }
+
+ var r0 driver.FileWriter
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, string, bool) (driver.FileWriter, error)); ok {
+ return rf(ctx, path, a)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, string, bool) driver.FileWriter); ok {
+ r0 = rf(ctx, path, a)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(driver.FileWriter)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, string, bool) error); ok {
+ r1 = rf(ctx, path, a)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// NewStorageDriver creates a new instance of StorageDriver. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewStorageDriver(t interface {
+ mock.TestingT
+ Cleanup(func())
+}) *StorageDriver {
+ mock := &StorageDriver{}
+ mock.Mock.Test(t)
+
+ t.Cleanup(func() { mock.AssertExpectations(t) })
+
+ return mock
+}
diff --git a/registry/app/api/controller/mocks/stream_producer.go b/registry/app/api/controller/mocks/stream_producer.go
new file mode 100644
index 000000000..d4f5509b3
--- /dev/null
+++ b/registry/app/api/controller/mocks/stream_producer.go
@@ -0,0 +1,49 @@
+// Code generated by mockery v2.20.0. DO NOT EDIT.
+
+package mocks
+
+import (
+ "context"
+
+ mock "github.com/stretchr/testify/mock"
+)
+
+// StreamProducer is an autogenerated mock type for the StreamProducer type
+type StreamProducer struct {
+ mock.Mock
+}
+
+// Send provides a mock function with given fields: ctx, topic, payload
+func (m *StreamProducer) Send(ctx context.Context, topic string, payload map[string]interface{}) (string, error) {
+ ret := m.Called(ctx, topic, payload)
+
+ var r0 string
+ if rf, ok := ret.Get(0).(func(context.Context, string, map[string]interface{}) string); ok {
+ r0 = rf(ctx, topic, payload)
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context, string, map[string]interface{}) error); ok {
+ r1 = rf(ctx, topic, payload)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// Close provides a mock function with given fields:
+func (m *StreamProducer) Close() error {
+ ret := m.Called()
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func() error); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
diff --git a/registry/app/api/controller/mocks/tag_repository.go b/registry/app/api/controller/mocks/tag_repository.go
new file mode 100644
index 000000000..793d7fe42
--- /dev/null
+++ b/registry/app/api/controller/mocks/tag_repository.go
@@ -0,0 +1,578 @@
+// Code generated by mockery v2.53.3. DO NOT EDIT.
+
+package mocks
+
+import (
+ context "context"
+
+ types "github.com/harness/gitness/registry/types"
+
+ mock "github.com/stretchr/testify/mock"
+)
+
+// TagRepository is an autogenerated mock type for the TagRepository type
+type TagRepository struct {
+ mock.Mock
+}
+
+// CountAllArtifactsByParentID provides a mock function with given fields: ctx, parentID, registryIDs, search, latestVersion, packageTypes
+func (_m *TagRepository) CountAllArtifactsByParentID(ctx context.Context, parentID int64, registryIDs *[]string, search string, latestVersion bool, packageTypes []string) (int64, error) {
+ ret := _m.Called(ctx, parentID, registryIDs, search, latestVersion, packageTypes)
+
+ if len(ret) == 0 {
+ panic("no return value specified for CountAllArtifactsByParentID")
+ }
+
+ var r0 int64
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, *[]string, string, bool, []string) (int64, error)); ok {
+ return rf(ctx, parentID, registryIDs, search, latestVersion, packageTypes)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, *[]string, string, bool, []string) int64); ok {
+ r0 = rf(ctx, parentID, registryIDs, search, latestVersion, packageTypes)
+ } else {
+ r0 = ret.Get(0).(int64)
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, *[]string, string, bool, []string) error); ok {
+ r1 = rf(ctx, parentID, registryIDs, search, latestVersion, packageTypes)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// CountAllArtifactsByRepo provides a mock function with given fields: ctx, parentID, repoKey, search, labels
+func (_m *TagRepository) CountAllArtifactsByRepo(ctx context.Context, parentID int64, repoKey string, search string, labels []string) (int64, error) {
+ ret := _m.Called(ctx, parentID, repoKey, search, labels)
+
+ if len(ret) == 0 {
+ panic("no return value specified for CountAllArtifactsByRepo")
+ }
+
+ var r0 int64
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string, []string) (int64, error)); ok {
+ return rf(ctx, parentID, repoKey, search, labels)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string, []string) int64); ok {
+ r0 = rf(ctx, parentID, repoKey, search, labels)
+ } else {
+ r0 = ret.Get(0).(int64)
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, string, string, []string) error); ok {
+ r1 = rf(ctx, parentID, repoKey, search, labels)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// CountAllTagsByRepoAndImage provides a mock function with given fields: ctx, parentID, repoKey, image, search
+func (_m *TagRepository) CountAllTagsByRepoAndImage(ctx context.Context, parentID int64, repoKey string, image string, search string) (int64, error) {
+ ret := _m.Called(ctx, parentID, repoKey, image, search)
+
+ if len(ret) == 0 {
+ panic("no return value specified for CountAllTagsByRepoAndImage")
+ }
+
+ var r0 int64
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string, string) (int64, error)); ok {
+ return rf(ctx, parentID, repoKey, image, search)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string, string) int64); ok {
+ r0 = rf(ctx, parentID, repoKey, image, search)
+ } else {
+ r0 = ret.Get(0).(int64)
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, string, string, string) error); ok {
+ r1 = rf(ctx, parentID, repoKey, image, search)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// CreateOrUpdate provides a mock function with given fields: ctx, t
+func (_m *TagRepository) CreateOrUpdate(ctx context.Context, t *types.Tag) error {
+ ret := _m.Called(ctx, t)
+
+ if len(ret) == 0 {
+ panic("no return value specified for CreateOrUpdate")
+ }
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, *types.Tag) error); ok {
+ r0 = rf(ctx, t)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// DeleteTag provides a mock function with given fields: ctx, registryID, imageName, name
+func (_m *TagRepository) DeleteTag(ctx context.Context, registryID int64, imageName string, name string) error {
+ ret := _m.Called(ctx, registryID, imageName, name)
+
+ if len(ret) == 0 {
+ panic("no return value specified for DeleteTag")
+ }
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string) error); ok {
+ r0 = rf(ctx, registryID, imageName, name)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// DeleteTagByManifestID provides a mock function with given fields: ctx, repoID, manifestID
+func (_m *TagRepository) DeleteTagByManifestID(ctx context.Context, repoID int64, manifestID int64) (bool, error) {
+ ret := _m.Called(ctx, repoID, manifestID)
+
+ if len(ret) == 0 {
+ panic("no return value specified for DeleteTagByManifestID")
+ }
+
+ var r0 bool
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, int64) (bool, error)); ok {
+ return rf(ctx, repoID, manifestID)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, int64) bool); ok {
+ r0 = rf(ctx, repoID, manifestID)
+ } else {
+ r0 = ret.Get(0).(bool)
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, int64) error); ok {
+ r1 = rf(ctx, repoID, manifestID)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// DeleteTagByName provides a mock function with given fields: ctx, repoID, name
+func (_m *TagRepository) DeleteTagByName(ctx context.Context, repoID int64, name string) (bool, error) {
+ ret := _m.Called(ctx, repoID, name)
+
+ if len(ret) == 0 {
+ panic("no return value specified for DeleteTagByName")
+ }
+
+ var r0 bool
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string) (bool, error)); ok {
+ return rf(ctx, repoID, name)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string) bool); ok {
+ r0 = rf(ctx, repoID, name)
+ } else {
+ r0 = ret.Get(0).(bool)
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, string) error); ok {
+ r1 = rf(ctx, repoID, name)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// DeleteTagsByImageName provides a mock function with given fields: ctx, registryID, imageName
+func (_m *TagRepository) DeleteTagsByImageName(ctx context.Context, registryID int64, imageName string) error {
+ ret := _m.Called(ctx, registryID, imageName)
+
+ if len(ret) == 0 {
+ panic("no return value specified for DeleteTagsByImageName")
+ }
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string) error); ok {
+ r0 = rf(ctx, registryID, imageName)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// FindTag provides a mock function with given fields: ctx, repoID, imageName, name
+func (_m *TagRepository) FindTag(ctx context.Context, repoID int64, imageName string, name string) (*types.Tag, error) {
+ ret := _m.Called(ctx, repoID, imageName, name)
+
+ if len(ret) == 0 {
+ panic("no return value specified for FindTag")
+ }
+
+ var r0 *types.Tag
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string) (*types.Tag, error)); ok {
+ return rf(ctx, repoID, imageName, name)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string) *types.Tag); ok {
+ r0 = rf(ctx, repoID, imageName, name)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.Tag)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, string, string) error); ok {
+ r1 = rf(ctx, repoID, imageName, name)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// GetAllArtifactsByParentID provides a mock function with given fields: ctx, parentID, registryIDs, sortByField, sortByOrder, limit, offset, search, latestVersion, packageTypes
+func (_m *TagRepository) GetAllArtifactsByParentID(ctx context.Context, parentID int64, registryIDs *[]string, sortByField string, sortByOrder string, limit int, offset int, search string, latestVersion bool, packageTypes []string) (*[]types.ArtifactMetadata, error) {
+ ret := _m.Called(ctx, parentID, registryIDs, sortByField, sortByOrder, limit, offset, search, latestVersion, packageTypes)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GetAllArtifactsByParentID")
+ }
+
+ var r0 *[]types.ArtifactMetadata
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, *[]string, string, string, int, int, string, bool, []string) (*[]types.ArtifactMetadata, error)); ok {
+ return rf(ctx, parentID, registryIDs, sortByField, sortByOrder, limit, offset, search, latestVersion, packageTypes)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, *[]string, string, string, int, int, string, bool, []string) *[]types.ArtifactMetadata); ok {
+ r0 = rf(ctx, parentID, registryIDs, sortByField, sortByOrder, limit, offset, search, latestVersion, packageTypes)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*[]types.ArtifactMetadata)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, *[]string, string, string, int, int, string, bool, []string) error); ok {
+ r1 = rf(ctx, parentID, registryIDs, sortByField, sortByOrder, limit, offset, search, latestVersion, packageTypes)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// GetAllArtifactsByRepo provides a mock function with given fields: ctx, parentID, repoKey, sortByField, sortByOrder, limit, offset, search, labels
+func (_m *TagRepository) GetAllArtifactsByRepo(ctx context.Context, parentID int64, repoKey string, sortByField string, sortByOrder string, limit int, offset int, search string, labels []string) (*[]types.ArtifactMetadata, error) {
+ ret := _m.Called(ctx, parentID, repoKey, sortByField, sortByOrder, limit, offset, search, labels)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GetAllArtifactsByRepo")
+ }
+
+ var r0 *[]types.ArtifactMetadata
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string, string, int, int, string, []string) (*[]types.ArtifactMetadata, error)); ok {
+ return rf(ctx, parentID, repoKey, sortByField, sortByOrder, limit, offset, search, labels)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string, string, int, int, string, []string) *[]types.ArtifactMetadata); ok {
+ r0 = rf(ctx, parentID, repoKey, sortByField, sortByOrder, limit, offset, search, labels)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*[]types.ArtifactMetadata)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, string, string, string, int, int, string, []string) error); ok {
+ r1 = rf(ctx, parentID, repoKey, sortByField, sortByOrder, limit, offset, search, labels)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// GetAllTagsByRepoAndImage provides a mock function with given fields: ctx, parentID, repoKey, image, sortByField, sortByOrder, limit, offset, search
+func (_m *TagRepository) GetAllTagsByRepoAndImage(ctx context.Context, parentID int64, repoKey string, image string, sortByField string, sortByOrder string, limit int, offset int, search string) (*[]types.TagMetadata, error) {
+ ret := _m.Called(ctx, parentID, repoKey, image, sortByField, sortByOrder, limit, offset, search)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GetAllTagsByRepoAndImage")
+ }
+
+ var r0 *[]types.TagMetadata
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string, string, string, int, int, string) (*[]types.TagMetadata, error)); ok {
+ return rf(ctx, parentID, repoKey, image, sortByField, sortByOrder, limit, offset, search)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string, string, string, int, int, string) *[]types.TagMetadata); ok {
+ r0 = rf(ctx, parentID, repoKey, image, sortByField, sortByOrder, limit, offset, search)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*[]types.TagMetadata)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, string, string, string, string, int, int, string) error); ok {
+ r1 = rf(ctx, parentID, repoKey, image, sortByField, sortByOrder, limit, offset, search)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// GetLatestTag provides a mock function with given fields: ctx, repoID, imageName
+func (_m *TagRepository) GetLatestTag(ctx context.Context, repoID int64, imageName string) (*types.Tag, error) {
+ ret := _m.Called(ctx, repoID, imageName)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GetLatestTag")
+ }
+
+ var r0 *types.Tag
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string) (*types.Tag, error)); ok {
+ return rf(ctx, repoID, imageName)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string) *types.Tag); ok {
+ r0 = rf(ctx, repoID, imageName)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.Tag)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, string) error); ok {
+ r1 = rf(ctx, repoID, imageName)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// GetLatestTagMetadata provides a mock function with given fields: ctx, parentID, repoKey, imageName
+func (_m *TagRepository) GetLatestTagMetadata(ctx context.Context, parentID int64, repoKey string, imageName string) (*types.ArtifactMetadata, error) {
+ ret := _m.Called(ctx, parentID, repoKey, imageName)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GetLatestTagMetadata")
+ }
+
+ var r0 *types.ArtifactMetadata
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string) (*types.ArtifactMetadata, error)); ok {
+ return rf(ctx, parentID, repoKey, imageName)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string) *types.ArtifactMetadata); ok {
+ r0 = rf(ctx, parentID, repoKey, imageName)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.ArtifactMetadata)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, string, string) error); ok {
+ r1 = rf(ctx, parentID, repoKey, imageName)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// GetLatestTagName provides a mock function with given fields: ctx, parentID, repoKey, imageName
+func (_m *TagRepository) GetLatestTagName(ctx context.Context, parentID int64, repoKey string, imageName string) (string, error) {
+ ret := _m.Called(ctx, parentID, repoKey, imageName)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GetLatestTagName")
+ }
+
+ var r0 string
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string) (string, error)); ok {
+ return rf(ctx, parentID, repoKey, imageName)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string) string); ok {
+ r0 = rf(ctx, parentID, repoKey, imageName)
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, string, string) error); ok {
+ r1 = rf(ctx, parentID, repoKey, imageName)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// GetTagDetail provides a mock function with given fields: ctx, repoID, imageName, name
+func (_m *TagRepository) GetTagDetail(ctx context.Context, repoID int64, imageName string, name string) (*types.TagDetail, error) {
+ ret := _m.Called(ctx, repoID, imageName, name)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GetTagDetail")
+ }
+
+ var r0 *types.TagDetail
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string) (*types.TagDetail, error)); ok {
+ return rf(ctx, repoID, imageName, name)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string) *types.TagDetail); ok {
+ r0 = rf(ctx, repoID, imageName, name)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.TagDetail)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, string, string) error); ok {
+ r1 = rf(ctx, repoID, imageName, name)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// GetTagMetadata provides a mock function with given fields: ctx, parentID, repoKey, imageName, name
+func (_m *TagRepository) GetTagMetadata(ctx context.Context, parentID int64, repoKey string, imageName string, name string) (*types.TagMetadata, error) {
+ ret := _m.Called(ctx, parentID, repoKey, imageName, name)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GetTagMetadata")
+ }
+
+ var r0 *types.TagMetadata
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string, string) (*types.TagMetadata, error)); ok {
+ return rf(ctx, parentID, repoKey, imageName, name)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, string, string) *types.TagMetadata); ok {
+ r0 = rf(ctx, parentID, repoKey, imageName, name)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.TagMetadata)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, string, string, string) error); ok {
+ r1 = rf(ctx, parentID, repoKey, imageName, name)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// HasTagsAfterName provides a mock function with given fields: ctx, repoID, filters
+func (_m *TagRepository) HasTagsAfterName(ctx context.Context, repoID int64, filters types.FilterParams) (bool, error) {
+ ret := _m.Called(ctx, repoID, filters)
+
+ if len(ret) == 0 {
+ panic("no return value specified for HasTagsAfterName")
+ }
+
+ var r0 bool
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, types.FilterParams) (bool, error)); ok {
+ return rf(ctx, repoID, filters)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, types.FilterParams) bool); ok {
+ r0 = rf(ctx, repoID, filters)
+ } else {
+ r0 = ret.Get(0).(bool)
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, types.FilterParams) error); ok {
+ r1 = rf(ctx, repoID, filters)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// LockTagByNameForUpdate provides a mock function with given fields: ctx, repoID, name
+func (_m *TagRepository) LockTagByNameForUpdate(ctx context.Context, repoID int64, name string) (bool, error) {
+ ret := _m.Called(ctx, repoID, name)
+
+ if len(ret) == 0 {
+ panic("no return value specified for LockTagByNameForUpdate")
+ }
+
+ var r0 bool
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string) (bool, error)); ok {
+ return rf(ctx, repoID, name)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string) bool); ok {
+ r0 = rf(ctx, repoID, name)
+ } else {
+ r0 = ret.Get(0).(bool)
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, string) error); ok {
+ r1 = rf(ctx, repoID, name)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// TagsPaginated provides a mock function with given fields: ctx, repoID, image, filters
+func (_m *TagRepository) TagsPaginated(ctx context.Context, repoID int64, image string, filters types.FilterParams) ([]*types.Tag, error) {
+ ret := _m.Called(ctx, repoID, image, filters)
+
+ if len(ret) == 0 {
+ panic("no return value specified for TagsPaginated")
+ }
+
+ var r0 []*types.Tag
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, types.FilterParams) ([]*types.Tag, error)); ok {
+ return rf(ctx, repoID, image, filters)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string, types.FilterParams) []*types.Tag); ok {
+ r0 = rf(ctx, repoID, image, filters)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]*types.Tag)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, string, types.FilterParams) error); ok {
+ r1 = rf(ctx, repoID, image, filters)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// NewTagRepository creates a new instance of TagRepository. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewTagRepository(t interface {
+ mock.TestingT
+ Cleanup(func())
+}) *TagRepository {
+ mock := &TagRepository{}
+ mock.Mock.Test(t)
+
+ t.Cleanup(func() { mock.AssertExpectations(t) })
+
+ return mock
+}
diff --git a/registry/app/api/controller/mocks/transaction.go b/registry/app/api/controller/mocks/transaction.go
new file mode 100644
index 000000000..ffc4037b6
--- /dev/null
+++ b/registry/app/api/controller/mocks/transaction.go
@@ -0,0 +1,33 @@
+// Code generated by mockery v2.14.0. DO NOT EDIT.
+
+package mocks
+
+import (
+ "context"
+
+ "github.com/stretchr/testify/mock"
+)
+
+// Transaction is an autogenerated mock type for the Transaction type
+type Transaction struct {
+ mock.Mock
+}
+
+// WithTx provides a mock function with given fields: ctx, fn, options
+func (m *Transaction) WithTx(ctx context.Context, fn func(context.Context) error, options ...interface{}) error {
+ var args []interface{}
+ args = append(args, ctx, fn)
+ for _, opt := range options {
+ args = append(args, opt)
+ }
+ ret := m.Called(args...)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, func(context.Context) error, ...interface{}) error); ok {
+ r0 = rf(ctx, fn, options...)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
diff --git a/registry/app/api/controller/mocks/transactor.go b/registry/app/api/controller/mocks/transactor.go
new file mode 100644
index 000000000..08bc477d4
--- /dev/null
+++ b/registry/app/api/controller/mocks/transactor.go
@@ -0,0 +1,38 @@
+// Code generated by mockery. DO NOT EDIT.
+
+package mocks
+
+import (
+ "context"
+
+ "github.com/stretchr/testify/mock"
+)
+
+// Transactor is a mock of dbtx.Transactor interface.
+type Transactor struct {
+ mock.Mock
+}
+
+// WithTx provides a mock function
+func (m *Transactor) WithTx(ctx context.Context, fn func(context.Context) error, opts ...interface{}) error {
+ args := m.Called(ctx, fn, opts)
+ return args.Error(0)
+}
+
+// BeginTx provides a mock function
+func (m *Transactor) BeginTx(ctx context.Context) (context.Context, error) {
+ args := m.Called(ctx)
+ return args.Get(0).(context.Context), args.Error(1)
+}
+
+// CommitTx provides a mock function
+func (m *Transactor) CommitTx(ctx context.Context) error {
+ args := m.Called(ctx)
+ return args.Error(0)
+}
+
+// RollbackTx provides a mock function
+func (m *Transactor) RollbackTx(ctx context.Context) error {
+ args := m.Called(ctx)
+ return args.Error(0)
+}
diff --git a/registry/app/api/controller/mocks/upstream_proxy_config_repository.go b/registry/app/api/controller/mocks/upstream_proxy_config_repository.go
new file mode 100644
index 000000000..0674b3c13
--- /dev/null
+++ b/registry/app/api/controller/mocks/upstream_proxy_config_repository.go
@@ -0,0 +1,242 @@
+// Code generated by mockery v2.53.3. DO NOT EDIT.
+
+package mocks
+
+import (
+ context "context"
+
+ types "github.com/harness/gitness/registry/types"
+
+ mock "github.com/stretchr/testify/mock"
+)
+
+// UpstreamProxyConfigRepository is an autogenerated mock type for the UpstreamProxyConfigRepository type
+type UpstreamProxyConfigRepository struct {
+ mock.Mock
+}
+
+// CountAll provides a mock function with given fields: ctx, parentID, packageTypes, search
+func (_m *UpstreamProxyConfigRepository) CountAll(ctx context.Context, parentID string, packageTypes []string, search string) (int64, error) {
+ ret := _m.Called(ctx, parentID, packageTypes, search)
+
+ if len(ret) == 0 {
+ panic("no return value specified for CountAll")
+ }
+
+ var r0 int64
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, string, []string, string) (int64, error)); ok {
+ return rf(ctx, parentID, packageTypes, search)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, string, []string, string) int64); ok {
+ r0 = rf(ctx, parentID, packageTypes, search)
+ } else {
+ r0 = ret.Get(0).(int64)
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, string, []string, string) error); ok {
+ r1 = rf(ctx, parentID, packageTypes, search)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// Create provides a mock function with given fields: ctx, upstreamproxyRecord
+func (_m *UpstreamProxyConfigRepository) Create(ctx context.Context, upstreamproxyRecord *types.UpstreamProxyConfig) (int64, error) {
+ ret := _m.Called(ctx, upstreamproxyRecord)
+
+ if len(ret) == 0 {
+ panic("no return value specified for Create")
+ }
+
+ var r0 int64
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, *types.UpstreamProxyConfig) (int64, error)); ok {
+ return rf(ctx, upstreamproxyRecord)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, *types.UpstreamProxyConfig) int64); ok {
+ r0 = rf(ctx, upstreamproxyRecord)
+ } else {
+ r0 = ret.Get(0).(int64)
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, *types.UpstreamProxyConfig) error); ok {
+ r1 = rf(ctx, upstreamproxyRecord)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// Delete provides a mock function with given fields: ctx, parentID, repoKey
+func (_m *UpstreamProxyConfigRepository) Delete(ctx context.Context, parentID int64, repoKey string) error {
+ ret := _m.Called(ctx, parentID, repoKey)
+
+ if len(ret) == 0 {
+ panic("no return value specified for Delete")
+ }
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string) error); ok {
+ r0 = rf(ctx, parentID, repoKey)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// Get provides a mock function with given fields: ctx, id
+func (_m *UpstreamProxyConfigRepository) Get(ctx context.Context, id int64) (*types.UpstreamProxy, error) {
+ ret := _m.Called(ctx, id)
+
+ if len(ret) == 0 {
+ panic("no return value specified for Get")
+ }
+
+ var r0 *types.UpstreamProxy
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64) (*types.UpstreamProxy, error)); ok {
+ return rf(ctx, id)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64) *types.UpstreamProxy); ok {
+ r0 = rf(ctx, id)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.UpstreamProxy)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok {
+ r1 = rf(ctx, id)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// GetAll provides a mock function with given fields: ctx, parentID, packageTypes, sortByField, sortByOrder, limit, offset, search
+func (_m *UpstreamProxyConfigRepository) GetAll(ctx context.Context, parentID int64, packageTypes []string, sortByField string, sortByOrder string, limit int, offset int, search string) (*[]types.UpstreamProxy, error) {
+ ret := _m.Called(ctx, parentID, packageTypes, sortByField, sortByOrder, limit, offset, search)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GetAll")
+ }
+
+ var r0 *[]types.UpstreamProxy
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, []string, string, string, int, int, string) (*[]types.UpstreamProxy, error)); ok {
+ return rf(ctx, parentID, packageTypes, sortByField, sortByOrder, limit, offset, search)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, []string, string, string, int, int, string) *[]types.UpstreamProxy); ok {
+ r0 = rf(ctx, parentID, packageTypes, sortByField, sortByOrder, limit, offset, search)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*[]types.UpstreamProxy)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, []string, string, string, int, int, string) error); ok {
+ r1 = rf(ctx, parentID, packageTypes, sortByField, sortByOrder, limit, offset, search)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// GetByParentID provides a mock function with given fields: ctx, parentID
+func (_m *UpstreamProxyConfigRepository) GetByParentID(ctx context.Context, parentID string) (*[]types.UpstreamProxy, error) {
+ ret := _m.Called(ctx, parentID)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GetByParentID")
+ }
+
+ var r0 *[]types.UpstreamProxy
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, string) (*[]types.UpstreamProxy, error)); ok {
+ return rf(ctx, parentID)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, string) *[]types.UpstreamProxy); ok {
+ r0 = rf(ctx, parentID)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*[]types.UpstreamProxy)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
+ r1 = rf(ctx, parentID)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// GetByRegistryIdentifier provides a mock function with given fields: ctx, parentID, repoKey
+func (_m *UpstreamProxyConfigRepository) GetByRegistryIdentifier(ctx context.Context, parentID int64, repoKey string) (*types.UpstreamProxy, error) {
+ ret := _m.Called(ctx, parentID, repoKey)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GetByRegistryIdentifier")
+ }
+
+ var r0 *types.UpstreamProxy
+ var r1 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string) (*types.UpstreamProxy, error)); ok {
+ return rf(ctx, parentID, repoKey)
+ }
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string) *types.UpstreamProxy); ok {
+ r0 = rf(ctx, parentID, repoKey)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.UpstreamProxy)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(context.Context, int64, string) error); ok {
+ r1 = rf(ctx, parentID, repoKey)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// Update provides a mock function with given fields: ctx, upstreamproxyRecord
+func (_m *UpstreamProxyConfigRepository) Update(ctx context.Context, upstreamproxyRecord *types.UpstreamProxyConfig) error {
+ ret := _m.Called(ctx, upstreamproxyRecord)
+
+ if len(ret) == 0 {
+ panic("no return value specified for Update")
+ }
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, *types.UpstreamProxyConfig) error); ok {
+ r0 = rf(ctx, upstreamproxyRecord)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// NewUpstreamProxyConfigRepository creates a new instance of UpstreamProxyConfigRepository. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewUpstreamProxyConfigRepository(t interface {
+ mock.TestingT
+ Cleanup(func())
+}) *UpstreamProxyConfigRepository {
+ mock := &UpstreamProxyConfigRepository{}
+ mock.Mock.Test(t)
+
+ t.Cleanup(func() { mock.AssertExpectations(t) })
+
+ return mock
+}
diff --git a/registry/app/api/controller/mocks/upstream_proxy_store.go b/registry/app/api/controller/mocks/upstream_proxy_store.go
new file mode 100644
index 000000000..46776db49
--- /dev/null
+++ b/registry/app/api/controller/mocks/upstream_proxy_store.go
@@ -0,0 +1,176 @@
+package mocks
+
+import (
+ "context"
+
+ "github.com/harness/gitness/registry/types"
+
+ "github.com/stretchr/testify/mock"
+)
+
+// UpstreamProxyStore is an autogenerated mock type for the UpstreamProxyConfigRepository type
+type UpstreamProxyStore struct {
+ mock.Mock
+}
+
+// Get provides a mock function with given fields: ctx, id
+func (m *UpstreamProxyStore) Get(ctx context.Context, id int64) (*types.UpstreamProxy, error) {
+ ret := m.Called(ctx, id)
+
+ var r0 *types.UpstreamProxy
+ if rf, ok := ret.Get(0).(func(context.Context, int64) *types.UpstreamProxy); ok {
+ r0 = rf(ctx, id)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.UpstreamProxy)
+ }
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok {
+ r1 = rf(ctx, id)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// GetByRegistryIdentifier provides a mock function with given fields: ctx, parentID, repoKey
+func (m *UpstreamProxyStore) GetByRegistryIdentifier(ctx context.Context, parentID int64, repoKey string) (*types.UpstreamProxy, error) {
+ ret := m.Called(ctx, parentID, repoKey)
+
+ var r0 *types.UpstreamProxy
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string) *types.UpstreamProxy); ok {
+ r0 = rf(ctx, parentID, repoKey)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.UpstreamProxy)
+ }
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context, int64, string) error); ok {
+ r1 = rf(ctx, parentID, repoKey)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// GetByParentID provides a mock function with given fields: ctx, parentID
+func (m *UpstreamProxyStore) GetByParentID(ctx context.Context, parentID string) (*[]types.UpstreamProxy, error) {
+ ret := m.Called(ctx, parentID)
+
+ var r0 *[]types.UpstreamProxy
+ if rf, ok := ret.Get(0).(func(context.Context, string) *[]types.UpstreamProxy); ok {
+ r0 = rf(ctx, parentID)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*[]types.UpstreamProxy)
+ }
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
+ r1 = rf(ctx, parentID)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// Create provides a mock function with given fields: ctx, upstreamproxyRecord
+func (m *UpstreamProxyStore) Create(ctx context.Context, upstreamproxyRecord *types.UpstreamProxyConfig) (int64, error) {
+ ret := m.Called(ctx, upstreamproxyRecord)
+
+ var r0 int64
+ if rf, ok := ret.Get(0).(func(context.Context, *types.UpstreamProxyConfig) int64); ok {
+ r0 = rf(ctx, upstreamproxyRecord)
+ } else {
+ r0 = ret.Get(0).(int64)
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context, *types.UpstreamProxyConfig) error); ok {
+ r1 = rf(ctx, upstreamproxyRecord)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// Delete provides a mock function with given fields: ctx, parentID, repoKey
+func (m *UpstreamProxyStore) Delete(ctx context.Context, parentID int64, repoKey string) error {
+ ret := m.Called(ctx, parentID, repoKey)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string) error); ok {
+ r0 = rf(ctx, parentID, repoKey)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// Update provides a mock function with given fields: ctx, upstreamproxyRecord
+func (m *UpstreamProxyStore) Update(ctx context.Context, upstreamproxyRecord *types.UpstreamProxyConfig) error {
+ ret := m.Called(ctx, upstreamproxyRecord)
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func(context.Context, *types.UpstreamProxyConfig) error); ok {
+ r0 = rf(ctx, upstreamproxyRecord)
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
+
+// GetAll provides a mock function with given fields: ctx, parentID, packageTypes, sortByField, sortByOrder, limit, offset, search
+func (m *UpstreamProxyStore) GetAll(ctx context.Context, parentID int64, packageTypes []string, sortByField string, sortByOrder string, limit int, offset int, search string) (*[]types.UpstreamProxy, error) {
+ ret := m.Called(ctx, parentID, packageTypes, sortByField, sortByOrder, limit, offset, search)
+
+ var r0 *[]types.UpstreamProxy
+ if rf, ok := ret.Get(0).(func(context.Context, int64, []string, string, string, int, int, string) *[]types.UpstreamProxy); ok {
+ r0 = rf(ctx, parentID, packageTypes, sortByField, sortByOrder, limit, offset, search)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*[]types.UpstreamProxy)
+ }
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context, int64, []string, string, string, int, int, string) error); ok {
+ r1 = rf(ctx, parentID, packageTypes, sortByField, sortByOrder, limit, offset, search)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// CountAll provides a mock function with given fields: ctx, parentID, packageTypes, search
+func (m *UpstreamProxyStore) CountAll(ctx context.Context, parentID string, packageTypes []string, search string) (int64, error) {
+ ret := m.Called(ctx, parentID, packageTypes, search)
+
+ var r0 int64
+ if rf, ok := ret.Get(0).(func(context.Context, string, []string, string) int64); ok {
+ r0 = rf(ctx, parentID, packageTypes, search)
+ } else {
+ r0 = ret.Get(0).(int64)
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context, string, []string, string) error); ok {
+ r1 = rf(ctx, parentID, packageTypes, search)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
diff --git a/registry/app/api/controller/mocks/url_provider.go b/registry/app/api/controller/mocks/url_provider.go
new file mode 100644
index 000000000..dfbb215c1
--- /dev/null
+++ b/registry/app/api/controller/mocks/url_provider.go
@@ -0,0 +1,337 @@
+// Code generated by mockery v2.53.3. DO NOT EDIT.
+
+package mocks
+
+import (
+ context "context"
+
+ mock "github.com/stretchr/testify/mock"
+)
+
+// Provider is an autogenerated mock type for the Provider type
+type Provider struct {
+ mock.Mock
+}
+
+// GenerateContainerGITCloneURL provides a mock function with given fields: ctx, repoPath
+func (_m *Provider) GenerateContainerGITCloneURL(ctx context.Context, repoPath string) string {
+ ret := _m.Called(ctx, repoPath)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GenerateContainerGITCloneURL")
+ }
+
+ var r0 string
+ if rf, ok := ret.Get(0).(func(context.Context, string) string); ok {
+ r0 = rf(ctx, repoPath)
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ return r0
+}
+
+// GenerateGITCloneSSHURL provides a mock function with given fields: ctx, repoPath
+func (_m *Provider) GenerateGITCloneSSHURL(ctx context.Context, repoPath string) string {
+ ret := _m.Called(ctx, repoPath)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GenerateGITCloneSSHURL")
+ }
+
+ var r0 string
+ if rf, ok := ret.Get(0).(func(context.Context, string) string); ok {
+ r0 = rf(ctx, repoPath)
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ return r0
+}
+
+// GenerateGITCloneURL provides a mock function with given fields: ctx, repoPath
+func (_m *Provider) GenerateGITCloneURL(ctx context.Context, repoPath string) string {
+ ret := _m.Called(ctx, repoPath)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GenerateGITCloneURL")
+ }
+
+ var r0 string
+ if rf, ok := ret.Get(0).(func(context.Context, string) string); ok {
+ r0 = rf(ctx, repoPath)
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ return r0
+}
+
+// GenerateUIBuildURL provides a mock function with given fields: ctx, repoPath, pipelineIdentifier, seqNumber
+func (_m *Provider) GenerateUIBuildURL(ctx context.Context, repoPath string, pipelineIdentifier string, seqNumber int64) string {
+ ret := _m.Called(ctx, repoPath, pipelineIdentifier, seqNumber)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GenerateUIBuildURL")
+ }
+
+ var r0 string
+ if rf, ok := ret.Get(0).(func(context.Context, string, string, int64) string); ok {
+ r0 = rf(ctx, repoPath, pipelineIdentifier, seqNumber)
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ return r0
+}
+
+// GenerateUICompareURL provides a mock function with given fields: ctx, repoPath, ref1, ref2
+func (_m *Provider) GenerateUICompareURL(ctx context.Context, repoPath string, ref1 string, ref2 string) string {
+ ret := _m.Called(ctx, repoPath, ref1, ref2)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GenerateUICompareURL")
+ }
+
+ var r0 string
+ if rf, ok := ret.Get(0).(func(context.Context, string, string, string) string); ok {
+ r0 = rf(ctx, repoPath, ref1, ref2)
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ return r0
+}
+
+// GenerateUIPRURL provides a mock function with given fields: ctx, repoPath, prID
+func (_m *Provider) GenerateUIPRURL(ctx context.Context, repoPath string, prID int64) string {
+ ret := _m.Called(ctx, repoPath, prID)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GenerateUIPRURL")
+ }
+
+ var r0 string
+ if rf, ok := ret.Get(0).(func(context.Context, string, int64) string); ok {
+ r0 = rf(ctx, repoPath, prID)
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ return r0
+}
+
+// GenerateUIRefURL provides a mock function with given fields: ctx, repoPath, ref
+func (_m *Provider) GenerateUIRefURL(ctx context.Context, repoPath string, ref string) string {
+ ret := _m.Called(ctx, repoPath, ref)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GenerateUIRefURL")
+ }
+
+ var r0 string
+ if rf, ok := ret.Get(0).(func(context.Context, string, string) string); ok {
+ r0 = rf(ctx, repoPath, ref)
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ return r0
+}
+
+// GenerateUIRegistryURL provides a mock function with given fields: ctx, parentSpacePath, registryName
+func (_m *Provider) GenerateUIRegistryURL(ctx context.Context, parentSpacePath string, registryName string) string {
+ ret := _m.Called(ctx, parentSpacePath, registryName)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GenerateUIRegistryURL")
+ }
+
+ var r0 string
+ if rf, ok := ret.Get(0).(func(context.Context, string, string) string); ok {
+ r0 = rf(ctx, parentSpacePath, registryName)
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ return r0
+}
+
+// GenerateUIRepoURL provides a mock function with given fields: ctx, repoPath
+func (_m *Provider) GenerateUIRepoURL(ctx context.Context, repoPath string) string {
+ ret := _m.Called(ctx, repoPath)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GenerateUIRepoURL")
+ }
+
+ var r0 string
+ if rf, ok := ret.Get(0).(func(context.Context, string) string); ok {
+ r0 = rf(ctx, repoPath)
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ return r0
+}
+
+// GetAPIHostname provides a mock function with given fields: ctx
+func (_m *Provider) GetAPIHostname(ctx context.Context) string {
+ ret := _m.Called(ctx)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GetAPIHostname")
+ }
+
+ var r0 string
+ if rf, ok := ret.Get(0).(func(context.Context) string); ok {
+ r0 = rf(ctx)
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ return r0
+}
+
+// GetAPIProto provides a mock function with given fields: ctx
+func (_m *Provider) GetAPIProto(ctx context.Context) string {
+ ret := _m.Called(ctx)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GetAPIProto")
+ }
+
+ var r0 string
+ if rf, ok := ret.Get(0).(func(context.Context) string); ok {
+ r0 = rf(ctx)
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ return r0
+}
+
+// GetGITHostname provides a mock function with given fields: ctx
+func (_m *Provider) GetGITHostname(ctx context.Context) string {
+ ret := _m.Called(ctx)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GetGITHostname")
+ }
+
+ var r0 string
+ if rf, ok := ret.Get(0).(func(context.Context) string); ok {
+ r0 = rf(ctx)
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ return r0
+}
+
+// GetInternalAPIURL provides a mock function with given fields: ctx
+func (_m *Provider) GetInternalAPIURL(ctx context.Context) string {
+ ret := _m.Called(ctx)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GetInternalAPIURL")
+ }
+
+ var r0 string
+ if rf, ok := ret.Get(0).(func(context.Context) string); ok {
+ r0 = rf(ctx)
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ return r0
+}
+
+// GetUIBaseURL provides a mock function with given fields: ctx, params
+func (_m *Provider) GetUIBaseURL(ctx context.Context, params ...string) string {
+ _va := make([]interface{}, len(params))
+ for _i := range params {
+ _va[_i] = params[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, ctx)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ if len(ret) == 0 {
+ panic("no return value specified for GetUIBaseURL")
+ }
+
+ var r0 string
+ if rf, ok := ret.Get(0).(func(context.Context, ...string) string); ok {
+ r0 = rf(ctx, params...)
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ return r0
+}
+
+// PackageURL provides a mock function with given fields: ctx, regRef, pkgType, params
+func (_m *Provider) PackageURL(ctx context.Context, regRef string, pkgType string, params ...string) string {
+ _va := make([]interface{}, len(params))
+ for _i := range params {
+ _va[_i] = params[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, ctx, regRef, pkgType)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ if len(ret) == 0 {
+ panic("no return value specified for PackageURL")
+ }
+
+ var r0 string
+ if rf, ok := ret.Get(0).(func(context.Context, string, string, ...string) string); ok {
+ r0 = rf(ctx, regRef, pkgType, params...)
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ return r0
+}
+
+// RegistryURL provides a mock function with given fields: ctx, params
+func (_m *Provider) RegistryURL(ctx context.Context, params ...string) string {
+ _va := make([]interface{}, len(params))
+ for _i := range params {
+ _va[_i] = params[_i]
+ }
+ var _ca []interface{}
+ _ca = append(_ca, ctx)
+ _ca = append(_ca, _va...)
+ ret := _m.Called(_ca...)
+
+ if len(ret) == 0 {
+ panic("no return value specified for RegistryURL")
+ }
+
+ var r0 string
+ if rf, ok := ret.Get(0).(func(context.Context, ...string) string); ok {
+ r0 = rf(ctx, params...)
+ } else {
+ r0 = ret.Get(0).(string)
+ }
+
+ return r0
+}
+
+// NewProvider creates a new instance of Provider. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewProvider(t interface {
+ mock.TestingT
+ Cleanup(func())
+}) *Provider {
+ mock := &Provider{}
+ mock.Mock.Test(t)
+
+ t.Cleanup(func() { mock.AssertExpectations(t) })
+
+ return mock
+}
diff --git a/registry/app/api/controller/mocks/webhook_service.go b/registry/app/api/controller/mocks/webhook_service.go
new file mode 100644
index 000000000..8d9cf5f6a
--- /dev/null
+++ b/registry/app/api/controller/mocks/webhook_service.go
@@ -0,0 +1,39 @@
+// Code generated by testify. DO NOT EDIT.
+
+package mocks
+
+import (
+ "context"
+
+ gitnesswebhook "github.com/harness/gitness/app/services/webhook"
+
+ "github.com/stretchr/testify/mock"
+)
+
+// WebhookService is a mock of WebhookService interface.
+type WebhookService struct {
+ mock.Mock
+}
+
+// ReTriggerWebhookExecution provides a mock function
+func (m *WebhookService) ReTriggerWebhookExecution(ctx context.Context, webhookExecutionID int64) (*gitnesswebhook.TriggerResult, error) {
+ ret := m.Called(ctx, webhookExecutionID)
+
+ var r0 *gitnesswebhook.TriggerResult
+ if rf, ok := ret.Get(0).(func(context.Context, int64) *gitnesswebhook.TriggerResult); ok {
+ r0 = rf(ctx, webhookExecutionID)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*gitnesswebhook.TriggerResult)
+ }
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok {
+ r1 = rf(ctx, webhookExecutionID)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
diff --git a/registry/app/api/controller/mocks/webhooks_execution_repository.go b/registry/app/api/controller/mocks/webhooks_execution_repository.go
new file mode 100644
index 000000000..c181259cc
--- /dev/null
+++ b/registry/app/api/controller/mocks/webhooks_execution_repository.go
@@ -0,0 +1,112 @@
+// Code generated by testify. DO NOT EDIT.
+
+package mocks
+
+import (
+ "context"
+
+ "github.com/harness/gitness/types"
+
+ "github.com/stretchr/testify/mock"
+)
+
+// WebhooksExecutionRepository is a mock of store.WebhooksExecutionRepository interface.
+type WebhooksExecutionRepository struct {
+ mock.Mock
+}
+
+// Find provides a mock function
+func (m *WebhooksExecutionRepository) Find(ctx context.Context, id int64) (*types.WebhookExecutionCore, error) {
+ ret := m.Called(ctx, id)
+
+ var r0 *types.WebhookExecutionCore
+ if rf, ok := ret.Get(0).(func(context.Context, int64) *types.WebhookExecutionCore); ok {
+ r0 = rf(ctx, id)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.WebhookExecutionCore)
+ }
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok {
+ r1 = rf(ctx, id)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// Create provides a mock function
+func (m *WebhooksExecutionRepository) Create(ctx context.Context, hook *types.WebhookExecutionCore) error {
+ ret := m.Called(ctx, hook)
+ return ret.Error(0)
+}
+
+// ListForWebhook provides a mock function
+func (m *WebhooksExecutionRepository) ListForWebhook(ctx context.Context, webhookID int64, limit int, page int, size int) ([]*types.WebhookExecutionCore, error) {
+ ret := m.Called(ctx, webhookID, limit, page, size)
+
+ var r0 []*types.WebhookExecutionCore
+ if rf, ok := ret.Get(0).(func(context.Context, int64, int, int, int) []*types.WebhookExecutionCore); ok {
+ r0 = rf(ctx, webhookID, limit, page, size)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]*types.WebhookExecutionCore)
+ }
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context, int64, int, int, int) error); ok {
+ r1 = rf(ctx, webhookID, limit, page, size)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// CountForWebhook provides a mock function
+func (m *WebhooksExecutionRepository) CountForWebhook(ctx context.Context, webhookID int64) (int64, error) {
+ ret := m.Called(ctx, webhookID)
+
+ var r0 int64
+ if rf, ok := ret.Get(0).(func(context.Context, int64) int64); ok {
+ r0 = rf(ctx, webhookID)
+ } else {
+ r0 = ret.Get(0).(int64)
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok {
+ r1 = rf(ctx, webhookID)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// ListForTrigger provides a mock function
+func (m *WebhooksExecutionRepository) ListForTrigger(ctx context.Context, triggerID string) ([]*types.WebhookExecutionCore, error) {
+ ret := m.Called(ctx, triggerID)
+
+ var r0 []*types.WebhookExecutionCore
+ if rf, ok := ret.Get(0).(func(context.Context, string) []*types.WebhookExecutionCore); ok {
+ r0 = rf(ctx, triggerID)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]*types.WebhookExecutionCore)
+ }
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
+ r1 = rf(ctx, triggerID)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
diff --git a/registry/app/api/controller/mocks/webhooks_repository.go b/registry/app/api/controller/mocks/webhooks_repository.go
new file mode 100644
index 000000000..91c9674a4
--- /dev/null
+++ b/registry/app/api/controller/mocks/webhooks_repository.go
@@ -0,0 +1,170 @@
+// Code generated by testify. DO NOT EDIT.
+
+package mocks
+
+import (
+ "context"
+
+ "github.com/harness/gitness/types"
+
+ "github.com/stretchr/testify/mock"
+)
+
+// WebhooksRepository is a mock of store.WebhooksRepository interface.
+type WebhooksRepository struct {
+ mock.Mock
+}
+
+// Create provides a mock function
+func (m *WebhooksRepository) Create(ctx context.Context, webhook *types.WebhookCore) error {
+ ret := m.Called(ctx, webhook)
+ return ret.Error(0)
+}
+
+// GetByRegistryAndIdentifier provides a mock function
+func (m *WebhooksRepository) GetByRegistryAndIdentifier(ctx context.Context, registryID int64, webhookIdentifier string) (*types.WebhookCore, error) {
+ ret := m.Called(ctx, registryID, webhookIdentifier)
+
+ var r0 *types.WebhookCore
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string) *types.WebhookCore); ok {
+ r0 = rf(ctx, registryID, webhookIdentifier)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.WebhookCore)
+ }
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context, int64, string) error); ok {
+ r1 = rf(ctx, registryID, webhookIdentifier)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// Find provides a mock function
+func (m *WebhooksRepository) Find(ctx context.Context, webhookID int64) (*types.WebhookCore, error) {
+ ret := m.Called(ctx, webhookID)
+
+ var r0 *types.WebhookCore
+ if rf, ok := ret.Get(0).(func(context.Context, int64) *types.WebhookCore); ok {
+ r0 = rf(ctx, webhookID)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.WebhookCore)
+ }
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok {
+ r1 = rf(ctx, webhookID)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// ListByRegistry provides a mock function
+func (m *WebhooksRepository) ListByRegistry(ctx context.Context, sortByField string, sortByOrder string, limit int, offset int, search string, registryID int64) ([]*types.WebhookCore, error) {
+ ret := m.Called(ctx, sortByField, sortByOrder, limit, offset, search, registryID)
+
+ var r0 []*types.WebhookCore
+ if rf, ok := ret.Get(0).(func(context.Context, string, string, int, int, string, int64) []*types.WebhookCore); ok {
+ r0 = rf(ctx, sortByField, sortByOrder, limit, offset, search, registryID)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]*types.WebhookCore)
+ }
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context, string, string, int, int, string, int64) error); ok {
+ r1 = rf(ctx, sortByField, sortByOrder, limit, offset, search, registryID)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// ListAllByRegistry provides a mock function
+func (m *WebhooksRepository) ListAllByRegistry(ctx context.Context, parents []types.WebhookParentInfo) ([]*types.WebhookCore, error) {
+ ret := m.Called(ctx, parents)
+
+ var r0 []*types.WebhookCore
+ if rf, ok := ret.Get(0).(func(context.Context, []types.WebhookParentInfo) []*types.WebhookCore); ok {
+ r0 = rf(ctx, parents)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]*types.WebhookCore)
+ }
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context, []types.WebhookParentInfo) error); ok {
+ r1 = rf(ctx, parents)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// CountAllByRegistry provides a mock function
+func (m *WebhooksRepository) CountAllByRegistry(ctx context.Context, registryID int64, search string) (int64, error) {
+ ret := m.Called(ctx, registryID, search)
+
+ var r0 int64
+ if rf, ok := ret.Get(0).(func(context.Context, int64, string) int64); ok {
+ r0 = rf(ctx, registryID, search)
+ } else {
+ r0 = ret.Get(0).(int64)
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context, int64, string) error); ok {
+ r1 = rf(ctx, registryID, search)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
+// Update provides a mock function
+func (m *WebhooksRepository) Update(ctx context.Context, webhook *types.WebhookCore) error {
+ ret := m.Called(ctx, webhook)
+ return ret.Error(0)
+}
+
+// DeleteByRegistryAndIdentifier provides a mock function
+func (m *WebhooksRepository) DeleteByRegistryAndIdentifier(ctx context.Context, registryID int64, webhookIdentifier string) error {
+ ret := m.Called(ctx, registryID, webhookIdentifier)
+ return ret.Error(0)
+}
+
+// UpdateOptLock provides a mock function
+func (m *WebhooksRepository) UpdateOptLock(ctx context.Context, hook *types.WebhookCore, fn func(hook *types.WebhookCore) error) (*types.WebhookCore, error) {
+ ret := m.Called(ctx, hook, fn)
+
+ var r0 *types.WebhookCore
+ if rf, ok := ret.Get(0).(func(context.Context, *types.WebhookCore, func(*types.WebhookCore) error) *types.WebhookCore); ok {
+ r0 = rf(ctx, hook, fn)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).(*types.WebhookCore)
+ }
+ }
+
+ var r1 error
+ if rf, ok := ret.Get(1).(func(context.Context, *types.WebhookCore, func(*types.WebhookCore) error) error); ok {
+ r1 = rf(ctx, hook, fn)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
diff --git a/registry/app/api/controller/metadata/interfaces.go b/registry/app/api/interfaces/registry_metadata.go
similarity index 54%
rename from registry/app/api/controller/metadata/interfaces.go
rename to registry/app/api/interfaces/registry_metadata.go
index 2bdb6463f..bd18895d4 100644
--- a/registry/app/api/controller/metadata/interfaces.go
+++ b/registry/app/api/interfaces/registry_metadata.go
@@ -1,4 +1,4 @@
-// Copyright 2023 Harness, Inc.
+// Copyright 2023 Harness, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,49 +12,59 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package metadata
+package interfaces
import (
"context"
- gitnesswebhook "github.com/harness/gitness/app/services/webhook"
api "github.com/harness/gitness/registry/app/api/openapi/contracts/artifact"
+ registrytypes "github.com/harness/gitness/registry/types"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
)
-type SpaceFinder interface {
- FindByRef(ctx context.Context, spaceRef string) (*types.SpaceCore, error)
- FindByID(ctx context.Context, spaceID int64) (*types.SpaceCore, error)
-}
-
+// RegistryMetadataHelper provides helper methods for registry metadata operations.
type RegistryMetadataHelper interface {
+ // GetRegistryRequestBaseInfo retrieves base info for registry request.
+ GetRegistryRequestBaseInfo(
+ ctx context.Context,
+ parentPath string,
+ identifier string,
+ ) (*registrytypes.RegistryRequestBaseInfo, error)
+
+ // GetPermissionChecks returns permission checks for registry operations.
GetPermissionChecks(
space *types.SpaceCore,
registryIdentifier string,
permission enum.Permission,
) []types.PermissionCheck
- GetRegistryRequestBaseInfo(
- ctx context.Context,
- parentRef string,
- regRef string,
- ) (*RegistryRequestBaseInfo, error)
- getSecretSpaceID(ctx context.Context, secretSpacePath *string) (int64, error)
- MapToAPIWebhookTriggers(triggers []enum.WebhookTrigger) []api.Trigger
- MapToInternalWebhookTriggers(
- triggers []api.Trigger,
- ) []enum.WebhookTrigger
+
+ // MapToWebhookCore maps webhook request to core webhook type.
MapToWebhookCore(
ctx context.Context,
webhookRequest api.WebhookRequest,
- regInfo *RegistryRequestBaseInfo,
+ regInfo *registrytypes.RegistryRequestBaseInfo,
) (*types.WebhookCore, error)
+
+ // MapToWebhookResponseEntity maps webhook core to response entity.
MapToWebhookResponseEntity(
ctx context.Context,
- createdWebhook *types.WebhookCore,
+ webhook *types.WebhookCore,
) (*api.Webhook, error)
-}
-type WebhookService interface {
- ReTriggerWebhookExecution(ctx context.Context, webhookExecutionID int64) (*gitnesswebhook.TriggerResult, error)
+ // MapToInternalWebhookTriggers maps webhook triggers to internal type.
+ MapToInternalWebhookTriggers(
+ triggers []api.Trigger,
+ ) []enum.WebhookTrigger
+
+ // MapToAPIWebhookTriggers maps webhook triggers to API type.
+ MapToAPIWebhookTriggers(
+ triggers []enum.WebhookTrigger,
+ ) []api.Trigger
+
+ // GetSecretSpaceID retrieves secret space ID from secret space path.
+ GetSecretSpaceID(
+ ctx context.Context,
+ secretSpacePath *string,
+ ) (int64, error)
}
diff --git a/registry/app/api/interfaces/space_finder.go b/registry/app/api/interfaces/space_finder.go
new file mode 100644
index 000000000..00b7fcaf3
--- /dev/null
+++ b/registry/app/api/interfaces/space_finder.go
@@ -0,0 +1,30 @@
+// Copyright 2023 Harness, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package interfaces
+
+import (
+ "context"
+
+ "github.com/harness/gitness/types"
+)
+
+// SpaceFinder defines the interface for finding spaces.
+type SpaceFinder interface {
+ // FindByID finds the space by id.
+ FindByID(ctx context.Context, id int64) (*types.SpaceCore, error)
+
+ // FindByRef finds the space using the spaceRef as either the id or the space path.
+ FindByRef(ctx context.Context, spaceRef string) (*types.SpaceCore, error)
+}
diff --git a/registry/app/api/router/harness/route.go b/registry/app/api/router/harness/route.go
index fe86f698f..86a150ba9 100644
--- a/registry/app/api/router/harness/route.go
+++ b/registry/app/api/router/harness/route.go
@@ -21,11 +21,11 @@ import (
"github.com/harness/gitness/app/api/middleware/encode"
"github.com/harness/gitness/app/auth/authn"
"github.com/harness/gitness/app/auth/authz"
- "github.com/harness/gitness/app/services/refcache"
corestore "github.com/harness/gitness/app/store"
urlprovider "github.com/harness/gitness/app/url"
"github.com/harness/gitness/audit"
"github.com/harness/gitness/registry/app/api/controller/metadata"
+ "github.com/harness/gitness/registry/app/api/interfaces"
"github.com/harness/gitness/registry/app/api/middleware"
"github.com/harness/gitness/registry/app/api/openapi/contracts/artifact"
storagedriver "github.com/harness/gitness/registry/app/driver"
@@ -64,7 +64,7 @@ func NewAPIHandler(
imageDao store.ImageRepository,
driver storagedriver.StorageDriver,
baseURL string,
- spaceFinder refcache.SpaceFinder,
+ spaceFinder interfaces.SpaceFinder,
tx dbtx.Transactor,
authenticator authn.Authenticator,
urlProvider urlprovider.Provider,
diff --git a/registry/services/webhook/interface.go b/registry/services/webhook/interface.go
new file mode 100644
index 000000000..2e5467555
--- /dev/null
+++ b/registry/services/webhook/interface.go
@@ -0,0 +1,26 @@
+// Copyright 2023 Harness, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package webhook
+
+import (
+ "context"
+
+ gitnesswebhook "github.com/harness/gitness/app/services/webhook"
+)
+
+// Service interface for webhook operations.
+type ServiceInterface interface {
+ ReTriggerWebhookExecution(ctx context.Context, webhookExecutionID int64) (*gitnesswebhook.TriggerResult, error)
+}
diff --git a/registry/services/webhook/service.go b/registry/services/webhook/service.go
index 4fb18160a..ca245c866 100644
--- a/registry/services/webhook/service.go
+++ b/registry/services/webhook/service.go
@@ -35,6 +35,9 @@ const (
eventsReaderGroupName = "gitness:webhook"
)
+// Verify Service implements ServiceInterface.
+var _ ServiceInterface = (*Service)(nil)
+
// Service is responsible for processing webhook events.
type Service struct {
WebhookExecutor *gitnesswebhook.WebhookExecutor
diff --git a/registry/types/request.go b/registry/types/request.go
new file mode 100644
index 000000000..e2aec36a7
--- /dev/null
+++ b/registry/types/request.go
@@ -0,0 +1,37 @@
+// Copyright 2023 Harness, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package types
+
+import (
+ api "github.com/harness/gitness/registry/app/api/openapi/contracts/artifact"
+)
+
+// RegistryRequestBaseInfo represents base information about a registry request.
+type RegistryRequestBaseInfo struct {
+ RootIdentifier string
+ RootIdentifierID int64
+ RegistryRef string
+ RegistryIdentifier string
+ RegistryID int64
+ ParentRef string
+ ParentID int64
+ RegistryType api.RegistryType
+ PackageType api.PackageType
+}
+
+// ArtifactFilesRequestInfo represents base information about an artifact files request.
+type ArtifactFilesRequestInfo struct {
+ RegistryRequestBaseInfo
+}
diff --git a/registry/utils/pointer_helpers.go b/registry/utils/pointer_helpers.go
new file mode 100644
index 000000000..b71edb99a
--- /dev/null
+++ b/registry/utils/pointer_helpers.go
@@ -0,0 +1,30 @@
+// Copyright 2023 Harness, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package utils
+
+import (
+ api "github.com/harness/gitness/registry/app/api/openapi/contracts/artifact"
+)
+
+// Helper functions for creating pointers.
+func StringPtr(s string) *string { return &s }
+func Int64Ptr(i int64) *int64 { return &i }
+func IntPtr(i int) *int { return &i }
+func BoolPtr(b bool) *bool { return &b }
+func Int32Ptr(i int32) *int32 { return &i }
+func WebhookExecResultPtr(r api.WebhookExecResult) *api.WebhookExecResult { return &r }
+func WebhookTriggerPtr(t api.Trigger) *api.Trigger { return &t }
+func PageSizePtr(i int32) *api.PageSize { size := api.PageSize(i); return &size }
+func PageNumberPtr(i int32) *api.PageNumber { num := api.PageNumber(i); return &num }