From 6dbe85fbfde5ad1c3ebfd50d4b652d228b8fca0a Mon Sep 17 00:00:00 2001 From: Dhruv Dhruv Date: Tue, 29 Oct 2024 04:46:03 +0000 Subject: [PATCH] fix: [CDE-413]: Setting branch URL in all gitspace API response (#2881) * fix: [CDE-413]: Adding spacePath to method. * fix: [CDE-413]: Adding method to get branch url in the scm interface and using it to set the branch url in the gitspace config api responses. Removing the SCM interface as it has only 1 impl. Minor refactoring. * fix: [CDE-413]: Adding method to get branch url in the scm interface and using it to set the branch url in the gitspace config api responses. Removing the SCM interface as it has only 1 impl. Minor refactoring. --- app/api/controller/gitspace/action.go | 3 ++ app/api/controller/gitspace/controller.go | 4 +- app/api/controller/gitspace/create.go | 1 + app/api/controller/gitspace/list_all.go | 4 ++ app/api/controller/gitspace/wire.go | 2 +- .../orchestrator/orchestrator_impl.go | 4 +- app/gitspace/orchestrator/wire.go | 2 +- app/gitspace/scm/gitness_scm.go | 32 +++++++++---- app/gitspace/scm/public_scm.go | 25 ++++++---- app/gitspace/scm/scm.go | 40 ++++++++-------- app/gitspace/scm/scm_factory.go | 18 -------- app/gitspace/scm/scm_provider.go | 46 +++++++++++++++++++ app/gitspace/scm/wire.go | 2 +- app/services/gitspace/find.go | 1 + app/services/gitspace/gitspace.go | 18 ++++++++ app/services/gitspace/wire.go | 5 +- cmd/gitness/wire_gen.go | 2 +- infraprovider/docker_provider.go | 10 +--- types/gitspace.go | 1 + 19 files changed, 146 insertions(+), 74 deletions(-) create mode 100644 app/gitspace/scm/scm_provider.go diff --git a/app/api/controller/gitspace/action.go b/app/api/controller/gitspace/action.go index b5fd39a69..86a9e6980 100644 --- a/app/api/controller/gitspace/action.go +++ b/app/api/controller/gitspace/action.go @@ -76,6 +76,9 @@ func (c *Controller) Action( return nil, err } } + + gitspaceConfig.BranchURL = c.gitspaceSvc.GetBranchURL(ctx, gitspaceConfig) + // All the actions should be idempotent. switch in.Action { case enum.GitspaceActionTypeStart: diff --git a/app/api/controller/gitspace/controller.go b/app/api/controller/gitspace/controller.go index b26c4e1b5..9dd09eb86 100644 --- a/app/api/controller/gitspace/controller.go +++ b/app/api/controller/gitspace/controller.go @@ -37,7 +37,7 @@ type Controller struct { gitspaceEventStore store.GitspaceEventStore tx dbtx.Transactor statefulLogger *logutil.StatefulLogger - scm scm.SCM + scm *scm.SCM repoStore store.RepoStore gitspaceSvc *gitspace.Service gitspaceLimiter limiter.Gitspace @@ -52,7 +52,7 @@ func NewController( spaceStore store.SpaceStore, gitspaceEventStore store.GitspaceEventStore, statefulLogger *logutil.StatefulLogger, - scm scm.SCM, + scm *scm.SCM, repoStore store.RepoStore, gitspaceSvc *gitspace.Service, gitspaceLimiter limiter.Gitspace, diff --git a/app/api/controller/gitspace/create.go b/app/api/controller/gitspace/create.go index 21393294d..f1b6e8f6f 100644 --- a/app/api/controller/gitspace/create.go +++ b/app/api/controller/gitspace/create.go @@ -177,6 +177,7 @@ func (c *Controller) Create( if err != nil { return nil, err } + gitspaceConfig.BranchURL = c.gitspaceSvc.GetBranchURL(ctx, gitspaceConfig) return gitspaceConfig, nil } diff --git a/app/api/controller/gitspace/list_all.go b/app/api/controller/gitspace/list_all.go index fbcb3dbea..14b102e89 100644 --- a/app/api/controller/gitspace/list_all.go +++ b/app/api/controller/gitspace/list_all.go @@ -75,6 +75,10 @@ func (c *Controller) ListAllGitspaces( // nolint:gocognit return nil, err } + for _, gitspaceConfig := range result { + gitspaceConfig.BranchURL = c.gitspaceSvc.GetBranchURL(ctx, gitspaceConfig) + } + return result, nil } diff --git a/app/api/controller/gitspace/wire.go b/app/api/controller/gitspace/wire.go index ab80a6904..c7471fb05 100644 --- a/app/api/controller/gitspace/wire.go +++ b/app/api/controller/gitspace/wire.go @@ -41,7 +41,7 @@ func ProvideController( spaceStore store.SpaceStore, eventStore store.GitspaceEventStore, statefulLogger *logutil.StatefulLogger, - scm scm.SCM, + scm *scm.SCM, repoStore store.RepoStore, gitspaceSvc *gitspace.Service, gitspaceLimiter limiter.Gitspace, diff --git a/app/gitspace/orchestrator/orchestrator_impl.go b/app/gitspace/orchestrator/orchestrator_impl.go index 4a898dc57..6deb50492 100644 --- a/app/gitspace/orchestrator/orchestrator_impl.go +++ b/app/gitspace/orchestrator/orchestrator_impl.go @@ -46,7 +46,7 @@ type Config struct { } type orchestrator struct { - scm scm.SCM + scm *scm.SCM infraProviderResourceStore store.InfraProviderResourceStore infraProvisioner infrastructure.InfraProvisioner containerOrchestrator container.Orchestrator @@ -60,7 +60,7 @@ type orchestrator struct { var _ Orchestrator = (*orchestrator)(nil) func NewOrchestrator( - scm scm.SCM, + scm *scm.SCM, infraProviderResourceStore store.InfraProviderResourceStore, infraProvisioner infrastructure.InfraProvisioner, containerOrchestrator container.Orchestrator, diff --git a/app/gitspace/orchestrator/wire.go b/app/gitspace/orchestrator/wire.go index 23f7ad13a..7d580d1f1 100644 --- a/app/gitspace/orchestrator/wire.go +++ b/app/gitspace/orchestrator/wire.go @@ -32,7 +32,7 @@ var WireSet = wire.NewSet( ) func ProvideOrchestrator( - scm scm.SCM, + scm *scm.SCM, infraProviderResourceStore store.InfraProviderResourceStore, infraProvisioner infrastructure.InfraProvisioner, containerOrchestrator container.Orchestrator, diff --git a/app/gitspace/scm/gitness_scm.go b/app/gitspace/scm/gitness_scm.go index a60e78893..203f810e0 100644 --- a/app/gitspace/scm/gitness_scm.go +++ b/app/gitspace/scm/gitness_scm.go @@ -49,9 +49,11 @@ type GitnessSCM struct { } // ListBranches implements Provider. -func (s *GitnessSCM) ListBranches(ctx context.Context, +func (s *GitnessSCM) ListBranches( + ctx context.Context, filter *BranchFilter, - _ *ResolvedCredentials) ([]Branch, error) { + _ *ResolvedCredentials, +) ([]Branch, error) { repo, err := s.repoStore.FindByRef(ctx, filter.Repository) if err != nil { return nil, fmt.Errorf("failed to find repo: %w", err) @@ -83,10 +85,12 @@ func mapBranch(b git.Branch) Branch { } } -// ListReporisotries implements Provider. -func (s *GitnessSCM) ListReporisotries(ctx context.Context, +// ListRepositories implements Provider. +func (s *GitnessSCM) ListRepositories( + ctx context.Context, filter *RepositoryFilter, - _ *ResolvedCredentials) ([]Repository, error) { + _ *ResolvedCredentials, +) ([]Repository, error) { repos, err := s.repoStore.List(ctx, filter.SpaceID, &types.RepoFilter{ Page: filter.Page, Size: filter.Size, @@ -125,10 +129,12 @@ func mapRepository(repo *types.Repository) (Repository, error) { }, nil } -func NewGitnessSCM(repoStore store.RepoStore, git git.Interface, +func NewGitnessSCM( + repoStore store.RepoStore, git git.Interface, tokenStore store.TokenStore, principalStore store.PrincipalStore, - urlProvider urlprovider.Provider) *GitnessSCM { + urlProvider urlprovider.Provider, +) *GitnessSCM { return &GitnessSCM{ repoStore: repoStore, git: git, @@ -138,7 +144,7 @@ func NewGitnessSCM(repoStore store.RepoStore, git git.Interface, } } -func (s GitnessSCM) ResolveCredentials( +func (s *GitnessSCM) ResolveCredentials( ctx context.Context, gitspaceConfig types.GitspaceConfig, ) (*ResolvedCredentials, error) { @@ -200,7 +206,8 @@ func (s GitnessSCM) ResolveCredentials( return resolvedCredentails, nil } -func (s GitnessSCM) GetFileContent(ctx context.Context, +func (s *GitnessSCM) GetFileContent( + ctx context.Context, gitspaceConfig types.GitspaceConfig, filePath string, _ *ResolvedCredentials, @@ -243,8 +250,13 @@ func (s GitnessSCM) GetFileContent(ctx context.Context, return catFileOutput, nil } -func findUserFromUID(ctx context.Context, +func findUserFromUID( + ctx context.Context, principalStore store.PrincipalStore, userUID string, ) (*types.User, error) { return principalStore.FindUserByUID(ctx, userUID) } + +func (s *GitnessSCM) GetBranchURL(_ string, repoURL string, branch string) (string, error) { + return fmt.Sprintf("%s/files/%s", strings.TrimSuffix(repoURL, ".git"), branch), nil +} diff --git a/app/gitspace/scm/public_scm.go b/app/gitspace/scm/public_scm.go index ef5ed4f3c..64b63b69d 100644 --- a/app/gitspace/scm/public_scm.go +++ b/app/gitspace/scm/public_scm.go @@ -31,6 +31,8 @@ import ( "github.com/rs/zerolog/log" ) +var _ Provider = (*GenericSCM)(nil) + type GenericSCM struct { } @@ -38,21 +40,24 @@ func NewGenericSCM() *GenericSCM { return &GenericSCM{} } -// ListBranches implements Provider. -func (s *GenericSCM) ListBranches(_ context.Context, +func (s *GenericSCM) ListBranches( + _ context.Context, _ *BranchFilter, - _ *ResolvedCredentials) ([]Branch, error) { + _ *ResolvedCredentials, +) ([]Branch, error) { return []Branch{}, nil } -// ListReporisotries implements Provider. -func (s *GenericSCM) ListReporisotries(_ context.Context, +func (s *GenericSCM) ListRepositories( + _ context.Context, _ *RepositoryFilter, - _ *ResolvedCredentials) ([]Repository, error) { + _ *ResolvedCredentials, +) ([]Repository, error) { return []Repository{}, nil } -func (s GenericSCM) GetFileContent(ctx context.Context, +func (s *GenericSCM) GetFileContent( + ctx context.Context, gitspaceConfig types.GitspaceConfig, filePath string, _ *ResolvedCredentials, @@ -115,7 +120,7 @@ func (s GenericSCM) GetFileContent(ctx context.Context, return catFileOutput.Bytes(), nil } -func (s GenericSCM) ResolveCredentials( +func (s *GenericSCM) ResolveCredentials( _ context.Context, gitspaceConfig types.GitspaceConfig, ) (*ResolvedCredentials, error) { @@ -131,3 +136,7 @@ func (s GenericSCM) ResolveCredentials( resolvedCredentials.RepoName = repoName return resolvedCredentials, err } + +func (s *GenericSCM) GetBranchURL(_ string, repoURL string, _ string) (string, error) { + return repoURL, nil +} diff --git a/app/gitspace/scm/scm.go b/app/gitspace/scm/scm.go index 66fca34b7..70466cfa3 100644 --- a/app/gitspace/scm/scm.go +++ b/app/gitspace/scm/scm.go @@ -34,29 +34,17 @@ var ( const devcontainerDefaultPath = ".devcontainer/devcontainer.json" -var _ SCM = (*scm)(nil) - -type SCM interface { - // GetSCMRepoDetails fetches repository name, credentials & devcontainer config file from the given repo and branch. - GetSCMRepoDetails( - ctx context.Context, - gitspaceConfig types.GitspaceConfig, - ) (*ResolvedDetails, error) - - // CheckValidCodeRepo checks if the current URL is a valid and accessible code repo, - // input can be connector info, user token etc. - CheckValidCodeRepo(ctx context.Context, request CodeRepositoryRequest) (*CodeRepositoryResponse, error) -} - -type scm struct { +type SCM struct { scmProviderFactory Factory } -func NewSCM(factory Factory) SCM { - return &scm{scmProviderFactory: factory} +func NewSCM(factory Factory) *SCM { + return &SCM{scmProviderFactory: factory} } -func (s scm) CheckValidCodeRepo( +// CheckValidCodeRepo checks if the current URL is a valid and accessible code repo, +// input can be connector info, user token etc. +func (s *SCM) CheckValidCodeRepo( ctx context.Context, codeRepositoryRequest CodeRepositoryRequest, ) (*CodeRepositoryResponse, error) { @@ -110,7 +98,8 @@ func (s scm) CheckValidCodeRepo( return codeRepositoryResponse, nil } -func (s scm) GetSCMRepoDetails( +// GetSCMRepoDetails fetches repository name, credentials & devcontainer config file from the given repo and branch. +func (s *SCM) GetSCMRepoDetails( ctx context.Context, gitspaceConfig types.GitspaceConfig, ) (*ResolvedDetails, error) { @@ -172,3 +161,16 @@ func detectDefaultGitBranch(ctx context.Context, gitRepoDir string) (string, err } return match[1], nil } + +func (s *SCM) GetBranchURL( + spacePath string, + repoType enum.GitspaceCodeRepoType, + repoURL string, + branch string, +) (string, error) { + scmProvider, err := s.scmProviderFactory.GetSCMProvider(repoType) + if err != nil { + return "", fmt.Errorf("failed to resolve scm provider while generating branch url: %w", err) + } + return scmProvider.GetBranchURL(spacePath, repoURL, branch) +} diff --git a/app/gitspace/scm/scm_factory.go b/app/gitspace/scm/scm_factory.go index 3511f3590..eed1a88ce 100644 --- a/app/gitspace/scm/scm_factory.go +++ b/app/gitspace/scm/scm_factory.go @@ -15,29 +15,11 @@ package scm import ( - "context" "fmt" - "github.com/harness/gitness/types" "github.com/harness/gitness/types/enum" ) -type Provider interface { - ResolveCredentials(ctx context.Context, gitspaceConfig types.GitspaceConfig) (*ResolvedCredentials, error) - GetFileContent( - ctx context.Context, - gitspaceConfig types.GitspaceConfig, - filePath string, - credentials *ResolvedCredentials, - ) ([]byte, error) - ListReporisotries(ctx context.Context, - filter *RepositoryFilter, - credentials *ResolvedCredentials) ([]Repository, error) - ListBranches(ctx context.Context, - filter *BranchFilter, - credentials *ResolvedCredentials) ([]Branch, error) -} - type Factory struct { providers map[enum.GitspaceCodeRepoType]Provider } diff --git a/app/gitspace/scm/scm_provider.go b/app/gitspace/scm/scm_provider.go new file mode 100644 index 000000000..fbca405cb --- /dev/null +++ b/app/gitspace/scm/scm_provider.go @@ -0,0 +1,46 @@ +// 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 scm + +import ( + "context" + + "github.com/harness/gitness/types" +) + +type Provider interface { + ResolveCredentials(ctx context.Context, gitspaceConfig types.GitspaceConfig) (*ResolvedCredentials, error) + + GetFileContent( + ctx context.Context, + gitspaceConfig types.GitspaceConfig, + filePath string, + credentials *ResolvedCredentials, + ) ([]byte, error) + + ListRepositories( + ctx context.Context, + filter *RepositoryFilter, + credentials *ResolvedCredentials, + ) ([]Repository, error) + + ListBranches( + ctx context.Context, + filter *BranchFilter, + credentials *ResolvedCredentials, + ) ([]Branch, error) + + GetBranchURL(spacePath string, repoURL string, branch string) (string, error) +} diff --git a/app/gitspace/scm/wire.go b/app/gitspace/scm/wire.go index edfad69c2..016f11aba 100644 --- a/app/gitspace/scm/wire.go +++ b/app/gitspace/scm/wire.go @@ -44,6 +44,6 @@ func ProvideFactory(gitness *GitnessSCM, genericSCM *GenericSCM) Factory { return NewFactory(gitness, genericSCM) } -func ProvideSCM(factory Factory) SCM { +func ProvideSCM(factory Factory) *SCM { return NewSCM(factory) } diff --git a/app/services/gitspace/find.go b/app/services/gitspace/find.go index 426062ad9..cbf790a46 100644 --- a/app/services/gitspace/find.go +++ b/app/services/gitspace/find.go @@ -50,6 +50,7 @@ func (c *Service) Find( if txErr != nil { return nil, txErr } + gitspaceConfigResult.BranchURL = c.GetBranchURL(ctx, gitspaceConfigResult) return gitspaceConfigResult, nil } diff --git a/app/services/gitspace/gitspace.go b/app/services/gitspace/gitspace.go index 1004b6af6..a576cd6a0 100644 --- a/app/services/gitspace/gitspace.go +++ b/app/services/gitspace/gitspace.go @@ -20,11 +20,14 @@ import ( gitspaceevents "github.com/harness/gitness/app/events/gitspace" "github.com/harness/gitness/app/gitspace/orchestrator" + "github.com/harness/gitness/app/gitspace/scm" "github.com/harness/gitness/app/services/infraprovider" "github.com/harness/gitness/app/store" "github.com/harness/gitness/store/database/dbtx" "github.com/harness/gitness/types" "github.com/harness/gitness/types/enum" + + "github.com/rs/zerolog/log" ) func NewService( @@ -36,6 +39,7 @@ func NewService( spaceStore store.SpaceStore, infraProviderSvc *infraprovider.Service, orchestrator orchestrator.Orchestrator, + scm *scm.SCM, ) *Service { return &Service{ tx: tx, @@ -46,6 +50,7 @@ func NewService( spaceStore: spaceStore, infraProviderSvc: infraProviderSvc, orchestrator: orchestrator, + scm: scm, } } @@ -58,6 +63,7 @@ type Service struct { tx dbtx.Transactor infraProviderSvc *infraprovider.Service orchestrator orchestrator.Orchestrator + scm *scm.SCM } func (c *Service) ListGitspacesForSpace( @@ -100,6 +106,7 @@ func (c *Service) ListGitspacesForSpace( } else { gitspaceConfig.State = enum.GitspaceStateUninitialized } + gitspaceConfig.BranchURL = c.GetBranchURL(ctx, gitspaceConfig) } return nil }, dbtx.TxDefaultReadOnly) @@ -127,3 +134,14 @@ func (c *Service) getLatestInstanceMap( } return gitspaceInstancesMap, nil } + +func (c *Service) GetBranchURL(ctx context.Context, config *types.GitspaceConfig) string { + branchURL, err := c.scm.GetBranchURL(config.SpacePath, config.CodeRepo.Type, config.CodeRepo.URL, + config.CodeRepo.Branch) + if err != nil { + log.Warn().Ctx(ctx).Err(err).Msgf("failed to get branch URL for gitspace config %s, returning repo url", + config.Identifier) + branchURL = config.CodeRepo.URL + } + return branchURL +} diff --git a/app/services/gitspace/wire.go b/app/services/gitspace/wire.go index de0539647..2916db69c 100644 --- a/app/services/gitspace/wire.go +++ b/app/services/gitspace/wire.go @@ -17,6 +17,7 @@ package gitspace import ( gitspaceevents "github.com/harness/gitness/app/events/gitspace" "github.com/harness/gitness/app/gitspace/orchestrator" + "github.com/harness/gitness/app/gitspace/scm" "github.com/harness/gitness/app/services/infraprovider" "github.com/harness/gitness/app/store" "github.com/harness/gitness/store/database/dbtx" @@ -37,8 +38,8 @@ func ProvideGitspace( spaceStore store.SpaceStore, infraProviderSvc *infraprovider.Service, orchestrator orchestrator.Orchestrator, - + scm *scm.SCM, ) *Service { return NewService(tx, gitspaceStore, gitspaceInstanceStore, eventReporter, - gitspaceEventStore, spaceStore, infraProviderSvc, orchestrator) + gitspaceEventStore, spaceStore, infraProviderSvc, orchestrator, scm) } diff --git a/cmd/gitness/wire_gen.go b/cmd/gitness/wire_gen.go index 89cb97226..ea5343023 100644 --- a/cmd/gitness/wire_gen.go +++ b/cmd/gitness/wire_gen.go @@ -323,7 +323,7 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro passwordResolver := secret.ProvidePasswordResolver() resolverFactory := secret.ProvideResolverFactory(passwordResolver) orchestratorOrchestrator := orchestrator.ProvideOrchestrator(scmSCM, infraProviderResourceStore, infraProvisioner, containerOrchestrator, eventsReporter, orchestratorConfig, vsCode, vsCodeWeb, resolverFactory) - gitspaceService := gitspace.ProvideGitspace(transactor, gitspaceConfigStore, gitspaceInstanceStore, eventsReporter, gitspaceEventStore, spaceStore, infraproviderService, orchestratorOrchestrator) + gitspaceService := gitspace.ProvideGitspace(transactor, gitspaceConfigStore, gitspaceInstanceStore, eventsReporter, gitspaceEventStore, spaceStore, infraproviderService, orchestratorOrchestrator, scmSCM) spaceController := space.ProvideController(config, transactor, provider, streamer, spaceIdentifier, authorizer, spacePathStore, pipelineStore, secretStore, connectorStore, templateStore, spaceStore, repoStore, principalStore, repoController, membershipStore, listService, repository, exporterRepository, resourceLimiter, publicaccessService, auditService, gitspaceService, labelService, instrumentService) reporter3, err := events5.ProvideReporter(eventsSystem) if err != nil { diff --git a/infraprovider/docker_provider.go b/infraprovider/docker_provider.go index 9c84ca8fb..3d05c87c1 100644 --- a/infraprovider/docker_provider.go +++ b/infraprovider/docker_provider.go @@ -152,15 +152,7 @@ func (d DockerProvider) Find( infrastructure.SpaceID = spaceID infrastructure.SpacePath = spacePath infrastructure.GitspaceConfigIdentifier = gitspaceConfigIdentifier - - name := volumeName(spacePath, gitspaceConfigIdentifier) - - volumeInspect, err := dockerClient.VolumeInspect(ctx, name) - if err != nil { - log.Err(err).Msgf("couldn't find the volume for %s", name) - } - - infrastructure.Storage = volumeInspect.Name + infrastructure.Storage = volumeName(spacePath, gitspaceConfigIdentifier) return infrastructure, nil } diff --git a/types/gitspace.go b/types/gitspace.go index be222b818..b35f8fc26 100644 --- a/types/gitspace.go +++ b/types/gitspace.go @@ -42,6 +42,7 @@ type CodeRepo struct { Ref *string `json:"code_repo_ref"` Type enum.GitspaceCodeRepoType `json:"code_repo_type"` Branch string `json:"branch"` + BranchURL string `json:"branch_url,omitempty"` DevcontainerPath *string `json:"devcontainer_path,omitempty"` IsPrivate bool `json:"code_repo_is_private"` AuthType string `json:"-"`