mirror of
https://github.com/harness/drone.git
synced 2025-05-16 08:59:56 +08:00
feat: [CDE-651]: add gitlab and bitbucket on-prem (#3674)
* feat: [CDE-651]: add gitlab and bitbucket on-prem * feat: [CDE-651]: add gitlab and bitbucket on-prem * feat: [CDE-651]: add gitlab and bitbucket on-prem * feat: [CDE-651]: add gitlab and bitbucket on-prem * feat: [CDE-651]: add gitlab and bitbucket on-prem * feat: [CDE-651]: add gitlab and bitbucket on-prem * feat: [CDE-651]: add gitlab and bitbucket on-prem * feat: [CDE-651]: add gitlab and bitbucket on-prem * feat: [CDE-651]: add gitlab and bitbucket on-prem * feat: [CDE-651]: add gitlab and bitbucket on-prem * feat: [CDE-603]: add SCM auth providers for bitbucket and gitlab feat: [CDE-651]: add gitlab and bitbucket on-prem * feat: [CDE-651]: add gitlab and bitbucket on-prem
This commit is contained in:
parent
46f6366728
commit
e03b053205
@ -240,7 +240,7 @@ func (e *EmbeddedDockerOrchestrator) startStoppedGitspace(
|
||||
}
|
||||
|
||||
// Set up git credentials if needed
|
||||
if resolvedRepoDetails.Credentials != nil {
|
||||
if resolvedRepoDetails.UserPasswordCredentials != nil {
|
||||
if err = utils.SetupGitCredentials(ctx, exec, resolvedRepoDetails, logStreamInstance); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -674,7 +674,7 @@ func (e *EmbeddedDockerOrchestrator) buildSetupSteps(
|
||||
exec *devcontainer.Exec,
|
||||
gitspaceLogger gitspaceTypes.GitspaceLogger,
|
||||
) error {
|
||||
if resolvedRepoDetails.ResolvedCredentials.Credentials != nil {
|
||||
if resolvedRepoDetails.ResolvedCredentials.UserPasswordCredentials != nil {
|
||||
return utils.SetupGitCredentials(ctx, exec, resolvedRepoDetails, gitspaceLogger)
|
||||
}
|
||||
return nil
|
||||
|
@ -91,9 +91,9 @@ func CloneCode(
|
||||
Branch: resolvedRepoDetails.Branch,
|
||||
RepoName: resolvedRepoDetails.RepoName,
|
||||
}
|
||||
if resolvedRepoDetails.ResolvedCredentials.Credentials != nil {
|
||||
data.Email = resolvedRepoDetails.Credentials.Email
|
||||
data.Name = resolvedRepoDetails.Credentials.Name.Value()
|
||||
if resolvedRepoDetails.ResolvedCredentials.UserPasswordCredentials != nil {
|
||||
data.Email = resolvedRepoDetails.UserPasswordCredentials.Email
|
||||
data.Name = resolvedRepoDetails.UserPasswordCredentials.Name.Value()
|
||||
}
|
||||
script, err := GenerateScriptFromTemplate(
|
||||
templateCloneCode, data)
|
||||
|
@ -35,7 +35,8 @@ import (
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
var _ Provider = (*GitnessSCM)(nil)
|
||||
var _ ListingProvider = (*GitnessSCM)(nil)
|
||||
var _ AuthAndFileContentProvider = (*GitnessSCM)(nil)
|
||||
|
||||
var gitspaceJWTLifetime = 720 * 24 * time.Hour
|
||||
|
||||
@ -50,7 +51,7 @@ type GitnessSCM struct {
|
||||
urlProvider urlprovider.Provider
|
||||
}
|
||||
|
||||
// ListBranches implements Provider.
|
||||
// ListBranches implements ListingProvider.
|
||||
func (s *GitnessSCM) ListBranches(
|
||||
ctx context.Context,
|
||||
filter *BranchFilter,
|
||||
@ -66,8 +67,8 @@ func (s *GitnessSCM) ListBranches(
|
||||
Query: filter.Query,
|
||||
Sort: git.BranchSortOptionDate,
|
||||
Order: git.SortOrderDesc,
|
||||
Page: int32(filter.Page),
|
||||
PageSize: int32(filter.Size),
|
||||
Page: filter.Page,
|
||||
PageSize: filter.Size,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -87,7 +88,7 @@ func mapBranch(b git.Branch) Branch {
|
||||
}
|
||||
}
|
||||
|
||||
// ListRepositories implements Provider.
|
||||
// ListRepositories implements ListingProvider.
|
||||
func (s *GitnessSCM) ListRepositories(
|
||||
ctx context.Context,
|
||||
filter *RepositoryFilter,
|
||||
@ -202,12 +203,12 @@ func (s *GitnessSCM) ResolveCredentials(
|
||||
userInfo := url.UserPassword("harness", jwtToken)
|
||||
modifiedURL.User = userInfo
|
||||
resolvedCredentails.CloneURL = types.NewMaskSecret(modifiedURL.String())
|
||||
credentials := &Credentials{
|
||||
credentials := &UserPasswordCredentials{
|
||||
Email: user.Email,
|
||||
Name: types.NewMaskSecret(user.DisplayName),
|
||||
Password: types.NewMaskSecret(jwtToken),
|
||||
}
|
||||
resolvedCredentails.Credentials = credentials
|
||||
resolvedCredentails.UserPasswordCredentials = credentials
|
||||
return resolvedCredentails, nil
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,8 @@ import (
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
var _ Provider = (*GenericSCM)(nil)
|
||||
var _ ListingProvider = (*GenericSCM)(nil)
|
||||
var _ AuthAndFileContentProvider = (*GenericSCM)(nil)
|
||||
|
||||
type GenericSCM struct {
|
||||
}
|
||||
|
@ -62,12 +62,12 @@ func (s *SCM) CheckValidCodeRepo(
|
||||
return codeRepositoryResponse, nil
|
||||
}
|
||||
|
||||
scmProvider, err := s.getSCMProvider(codeRepositoryRequest.RepoType)
|
||||
authAndFileContentProvider, err := s.getSCMAuthAndFileProvider(codeRepositoryRequest.RepoType)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to resolve SCM provider: %w", err)
|
||||
}
|
||||
|
||||
resolvedCreds, err := s.resolveRepoCredentials(ctx, scmProvider, codeRepositoryRequest)
|
||||
resolvedCreds, err := s.resolveRepoCredentials(ctx, authAndFileContentProvider, codeRepositoryRequest)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to resolve repo credentials and URL: %w", err)
|
||||
}
|
||||
@ -83,17 +83,21 @@ func (s *SCM) GetSCMRepoDetails(
|
||||
ctx context.Context,
|
||||
gitspaceConfig types.GitspaceConfig,
|
||||
) (*ResolvedDetails, error) {
|
||||
scmProvider, err := s.getSCMProvider(gitspaceConfig.CodeRepo.Type)
|
||||
scmAuthAndFileContentProvider, err := s.getSCMAuthAndFileProvider(gitspaceConfig.CodeRepo.Type)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to resolve SCM provider: %w", err)
|
||||
return nil, fmt.Errorf("failed to resolve SCM Auth and File COntent provider: %w", err)
|
||||
}
|
||||
|
||||
resolvedCredentials, err := scmProvider.ResolveCredentials(ctx, gitspaceConfig)
|
||||
resolvedCredentials, err := scmAuthAndFileContentProvider.ResolveCredentials(ctx, gitspaceConfig)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to resolve repo credentials and url: %w", err)
|
||||
}
|
||||
|
||||
devcontainerConfig, err := s.getDevcontainerConfig(ctx, scmProvider, gitspaceConfig, resolvedCredentials)
|
||||
scmAuthAndFileProvider, err := s.getSCMAuthAndFileProvider(gitspaceConfig.CodeRepo.Type)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to resolve SCM Auth and File content provider: %w", err)
|
||||
}
|
||||
devcontainerConfig, err := s.getDevcontainerConfig(ctx, scmAuthAndFileProvider, gitspaceConfig, resolvedCredentials)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read or parse devcontainer config: %w", err)
|
||||
}
|
||||
@ -148,16 +152,16 @@ func (s *SCM) detectBranch(ctx context.Context, repoURL string) (string, error)
|
||||
return defaultBranch, nil
|
||||
}
|
||||
|
||||
func (s *SCM) getSCMProvider(repoType enum.GitspaceCodeRepoType) (Provider, error) {
|
||||
func (s *SCM) getSCMAuthAndFileProvider(repoType enum.GitspaceCodeRepoType) (AuthAndFileContentProvider, error) {
|
||||
if repoType == "" {
|
||||
repoType = enum.CodeRepoTypeUnknown
|
||||
}
|
||||
return s.scmProviderFactory.GetSCMProvider(repoType)
|
||||
return s.scmProviderFactory.GetSCMAuthAndFileProvider(repoType)
|
||||
}
|
||||
|
||||
func (s *SCM) resolveRepoCredentials(
|
||||
ctx context.Context,
|
||||
scmProvider Provider,
|
||||
authAndFileContentProvider AuthAndFileContentProvider,
|
||||
codeRepositoryRequest CodeRepositoryRequest,
|
||||
) (*ResolvedCredentials, error) {
|
||||
codeRepo := types.CodeRepo{URL: codeRepositoryRequest.URL}
|
||||
@ -167,18 +171,19 @@ func (s *SCM) resolveRepoCredentials(
|
||||
SpacePath: codeRepositoryRequest.SpacePath,
|
||||
GitspaceUser: gitspaceUser,
|
||||
}
|
||||
return scmProvider.ResolveCredentials(ctx, gitspaceConfig)
|
||||
return authAndFileContentProvider.ResolveCredentials(ctx, gitspaceConfig)
|
||||
}
|
||||
|
||||
func (s *SCM) getDevcontainerConfig(
|
||||
ctx context.Context,
|
||||
scmProvider Provider,
|
||||
scmAuthAndFileContentProvider AuthAndFileContentProvider,
|
||||
gitspaceConfig types.GitspaceConfig,
|
||||
resolvedCredentials *ResolvedCredentials,
|
||||
) (types.DevcontainerConfig, error) {
|
||||
config := types.DevcontainerConfig{}
|
||||
filePath := devcontainerDefaultPath
|
||||
catFileOutputBytes, err := scmProvider.GetFileContent(ctx, gitspaceConfig, filePath, resolvedCredentials)
|
||||
catFileOutputBytes, err := scmAuthAndFileContentProvider.GetFileContent(
|
||||
ctx, gitspaceConfig, filePath, resolvedCredentials)
|
||||
if err != nil {
|
||||
return config, fmt.Errorf("failed to read devcontainer file: %w", err)
|
||||
}
|
||||
|
31
app/gitspace/scm/scm_auth_file_provider.go
Normal file
31
app/gitspace/scm/scm_auth_file_provider.go
Normal file
@ -0,0 +1,31 @@
|
||||
// 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 AuthAndFileContentProvider interface {
|
||||
GetFileContent(
|
||||
ctx context.Context,
|
||||
gitspaceConfig types.GitspaceConfig,
|
||||
filePath string,
|
||||
credentials *ResolvedCredentials,
|
||||
) ([]byte, error)
|
||||
ResolveCredentials(ctx context.Context, gitspaceConfig types.GitspaceConfig) (*ResolvedCredentials, error)
|
||||
}
|
@ -21,22 +21,41 @@ import (
|
||||
)
|
||||
|
||||
type Factory struct {
|
||||
providers map[enum.GitspaceCodeRepoType]Provider
|
||||
listingProviders map[enum.GitspaceCodeRepoType]ListingProvider
|
||||
authAndFileProviders map[enum.GitspaceCodeRepoType]AuthAndFileContentProvider
|
||||
}
|
||||
|
||||
func NewFactoryWithProviders(providers map[enum.GitspaceCodeRepoType]Provider) Factory {
|
||||
return Factory{providers: providers}
|
||||
func NewFactoryWithProviders(
|
||||
providers map[enum.GitspaceCodeRepoType]ListingProvider,
|
||||
authProviders map[enum.GitspaceCodeRepoType]AuthAndFileContentProvider) Factory {
|
||||
return Factory{listingProviders: providers,
|
||||
authAndFileProviders: authProviders}
|
||||
}
|
||||
|
||||
func NewFactory(gitnessProvider *GitnessSCM, genericSCM *GenericSCM) Factory {
|
||||
providers := make(map[enum.GitspaceCodeRepoType]Provider)
|
||||
providers[enum.CodeRepoTypeGitness] = gitnessProvider
|
||||
providers[enum.CodeRepoTypeUnknown] = genericSCM
|
||||
return Factory{providers: providers}
|
||||
listingProviders := make(map[enum.GitspaceCodeRepoType]ListingProvider)
|
||||
listingProviders[enum.CodeRepoTypeGitness] = gitnessProvider
|
||||
listingProviders[enum.CodeRepoTypeUnknown] = genericSCM
|
||||
authAndFileContentProviders := make(map[enum.GitspaceCodeRepoType]AuthAndFileContentProvider)
|
||||
authAndFileContentProviders[enum.CodeRepoTypeGitness] = gitnessProvider
|
||||
authAndFileContentProviders[enum.CodeRepoTypeUnknown] = genericSCM
|
||||
return Factory{
|
||||
listingProviders: listingProviders,
|
||||
authAndFileProviders: authAndFileContentProviders,
|
||||
}
|
||||
}
|
||||
|
||||
func (f *Factory) GetSCMProvider(providerType enum.GitspaceCodeRepoType) (Provider, error) {
|
||||
val := f.providers[providerType]
|
||||
func (f *Factory) GetSCMProvider(providerType enum.GitspaceCodeRepoType) (ListingProvider, error) {
|
||||
val := f.listingProviders[providerType]
|
||||
if val == nil {
|
||||
return nil, fmt.Errorf("unknown scm provider type: %s", providerType)
|
||||
}
|
||||
return val, nil
|
||||
}
|
||||
|
||||
func (f *Factory) GetSCMAuthAndFileProvider(providerType enum.GitspaceCodeRepoType) (
|
||||
AuthAndFileContentProvider, error) {
|
||||
val := f.authAndFileProviders[providerType]
|
||||
if val == nil {
|
||||
return nil, fmt.Errorf("unknown scm provider type: %s", providerType)
|
||||
}
|
||||
|
@ -16,20 +16,9 @@ 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)
|
||||
|
||||
type ListingProvider interface {
|
||||
ListRepositories(
|
||||
ctx context.Context,
|
||||
filter *RepositoryFilter,
|
@ -33,26 +33,50 @@ type CodeRepositoryResponse struct {
|
||||
CodeRepoIsPrivate bool `json:"is_private"`
|
||||
}
|
||||
|
||||
// CredentialType represents the type of credential.
|
||||
type CredentialType string
|
||||
|
||||
const (
|
||||
CredentialTypeUserPassword CredentialType = "user_password"
|
||||
CredentialTypeOAuthTokenRef CredentialType = "oauth_token_ref" // #nosec G101
|
||||
)
|
||||
|
||||
type (
|
||||
ResolvedDetails struct {
|
||||
ResolvedCredentials
|
||||
DevcontainerConfig types.DevcontainerConfig
|
||||
}
|
||||
|
||||
// Credentials contains login and initialization information used
|
||||
// UserPasswordCredentials contains login and initialization information used
|
||||
// by an automated login process.
|
||||
Credentials struct {
|
||||
UserPasswordCredentials struct {
|
||||
Email string
|
||||
Name types.MaskSecret
|
||||
Password types.MaskSecret
|
||||
}
|
||||
|
||||
OAuth2ClientRefCredentials struct {
|
||||
ClientID string
|
||||
ClientSecretRef string
|
||||
GrantType string
|
||||
RedirectURI string
|
||||
Code string
|
||||
}
|
||||
|
||||
OAuth2TokenRefCredentials struct {
|
||||
UserPasswordCredentials
|
||||
RefreshTokenRef string
|
||||
AccessTokenRef string
|
||||
}
|
||||
|
||||
ResolvedCredentials struct {
|
||||
Branch string
|
||||
// CloneURL contains credentials for private repositories in url prefix
|
||||
CloneURL types.MaskSecret
|
||||
Credentials *Credentials
|
||||
RepoName string
|
||||
CloneURL types.MaskSecret
|
||||
UserPasswordCredentials *UserPasswordCredentials
|
||||
OAuth2TokenRefCredentials *OAuth2TokenRefCredentials
|
||||
RepoName string
|
||||
CredentialType CredentialType
|
||||
}
|
||||
|
||||
RepositoryFilter struct {
|
||||
@ -67,8 +91,8 @@ type (
|
||||
SpaceID int64 `json:"space_id"`
|
||||
Repository string `json:"repo"`
|
||||
Query string `json:"query"`
|
||||
Page int `json:"page"`
|
||||
Size int `json:"size"`
|
||||
Page int32 `json:"page"`
|
||||
Size int32 `json:"size"`
|
||||
RepoURL string `json:"repo_url"`
|
||||
}
|
||||
|
||||
|
@ -25,13 +25,21 @@ var codeRepoTypes = []GitspaceCodeRepoType{
|
||||
CodeRepoTypeBitbucket,
|
||||
CodeRepoTypeUnknown,
|
||||
CodeRepoTypeGitness,
|
||||
CodeRepoTypeGitlabOnPrem,
|
||||
CodeRepoTypeBitbucketServer,
|
||||
}
|
||||
|
||||
const (
|
||||
CodeRepoTypeGithub GitspaceCodeRepoType = "github"
|
||||
CodeRepoTypeGitlab GitspaceCodeRepoType = "gitlab"
|
||||
CodeRepoTypeGitness GitspaceCodeRepoType = "gitness"
|
||||
CodeRepoTypeHarnessCode GitspaceCodeRepoType = "harness_code"
|
||||
CodeRepoTypeBitbucket GitspaceCodeRepoType = "bitbucket"
|
||||
CodeRepoTypeUnknown GitspaceCodeRepoType = "unknown"
|
||||
CodeRepoTypeGithub GitspaceCodeRepoType = "github"
|
||||
CodeRepoTypeGitlab GitspaceCodeRepoType = "gitlab"
|
||||
CodeRepoTypeGitness GitspaceCodeRepoType = "gitness"
|
||||
CodeRepoTypeHarnessCode GitspaceCodeRepoType = "harness_code"
|
||||
CodeRepoTypeBitbucket GitspaceCodeRepoType = "bitbucket"
|
||||
CodeRepoTypeUnknown GitspaceCodeRepoType = "unknown"
|
||||
CodeRepoTypeGitlabOnPrem GitspaceCodeRepoType = "gitlab_on_prem"
|
||||
CodeRepoTypeBitbucketServer GitspaceCodeRepoType = "bitbucket_server"
|
||||
)
|
||||
|
||||
func (p GitspaceCodeRepoType) IsOnPrem() bool {
|
||||
return p == CodeRepoTypeGitlabOnPrem || p == CodeRepoTypeBitbucketServer
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user