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:"-"`