From f3c0d4ae4b576ff1f3e96e622e3cb60faf330ea1 Mon Sep 17 00:00:00 2001 From: Ivan Dagelic Date: Fri, 11 Oct 2024 16:52:54 +0200 Subject: [PATCH] feat: choice between multiple git provider configs (#1233) Signed-off-by: Ivan Dagelic --- .../workspaces/mocks/git_provider_service.go | 4 +- pkg/agent/agent.go | 6 +- .../controllers/gitprovider/gitprovider.go | 53 +++++- pkg/api/docs/docs.go | 39 ++++- pkg/api/docs/swagger.json | 39 ++++- pkg/api/docs/swagger.yaml | 29 +++- pkg/api/middlewares/auth.go | 11 ++ pkg/api/server.go | 3 +- pkg/apiclient/README.md | 3 +- pkg/apiclient/api/openapi.yaml | 30 +++- pkg/apiclient/api_git_provider.go | 156 +++++++++++++++--- pkg/apiclient/docs/GitProviderAPI.md | 93 +++++++++-- pkg/build/mocks/gitprovider_config_store.go | 4 +- pkg/build/runner.go | 12 +- pkg/build/runner_test.go | 2 +- pkg/cmd/workspace/create.go | 16 ++ pkg/cmd/workspace/util/creation_data.go | 25 ++- pkg/cmd/workspace/util/repository_wizard.go | 28 ++-- pkg/cmd/workspacemode/git_cred.go | 32 +++- pkg/server/gitproviders/config.go | 93 +++++++++++ pkg/server/gitproviders/gitprovider.go | 83 ---------- pkg/server/gitproviders/service.go | 10 +- pkg/server/workspaces/create.go | 20 ++- pkg/server/workspaces/service_test.go | 4 +- 24 files changed, 603 insertions(+), 192 deletions(-) create mode 100644 pkg/server/gitproviders/config.go diff --git a/internal/testing/server/workspaces/mocks/git_provider_service.go b/internal/testing/server/workspaces/mocks/git_provider_service.go index 6dfa5f1a9b..a58a54c763 100644 --- a/internal/testing/server/workspaces/mocks/git_provider_service.go +++ b/internal/testing/server/workspaces/mocks/git_provider_service.go @@ -25,9 +25,9 @@ func (m *MockGitProviderService) GetConfig(id string) (*gitprovider.GitProviderC return args.Get(0).(*gitprovider.GitProviderConfig), args.Error(1) } -func (m *MockGitProviderService) GetConfigForUrl(url string) (*gitprovider.GitProviderConfig, error) { +func (m *MockGitProviderService) ListConfigsForUrl(url string) ([]*gitprovider.GitProviderConfig, error) { args := m.Called(url) - return args.Get(0).(*gitprovider.GitProviderConfig), args.Error(1) + return args.Get(0).([]*gitprovider.GitProviderConfig), args.Error(1) } func (m *MockGitProviderService) GetGitProviderForHttpRequest(req *http.Request) (gitprovider.GitProvider, error) { diff --git a/pkg/agent/agent.go b/pkg/agent/agent.go index d6b5e74d66..a22381f4f0 100644 --- a/pkg/agent/agent.go +++ b/pkg/agent/agent.go @@ -162,13 +162,13 @@ func (a *Agent) getGitProvider(repoUrl string) (*apiclient.GitProvider, error) { } encodedUrl := url.QueryEscape(repoUrl) - gitProvider, res, err := apiClient.GitProviderAPI.GetGitProviderForUrl(ctx, encodedUrl).Execute() + gitProviders, res, err := apiClient.GitProviderAPI.ListGitProvidersForUrl(ctx, encodedUrl).Execute() if err != nil { return nil, apiclient_util.HandleErrorResponse(res, err) } - if gitProvider != nil { - return gitProvider, nil + if len(gitProviders) > 0 { + return &gitProviders[0], nil } return nil, nil diff --git a/pkg/api/controllers/gitprovider/gitprovider.go b/pkg/api/controllers/gitprovider/gitprovider.go index 3469f34156..315f12dca4 100644 --- a/pkg/api/controllers/gitprovider/gitprovider.go +++ b/pkg/api/controllers/gitprovider/gitprovider.go @@ -13,6 +13,7 @@ import ( "github.com/daytonaio/daytona/pkg/api/controllers" "github.com/daytonaio/daytona/pkg/api/controllers/gitprovider/dto" + "github.com/daytonaio/daytona/pkg/apikey" "github.com/daytonaio/daytona/pkg/gitprovider" "github.com/daytonaio/daytona/pkg/server" "github.com/gin-gonic/gin" @@ -46,18 +47,18 @@ func ListGitProviders(ctx *gin.Context) { ctx.JSON(200, response) } -// GetGitProviderForUrl godoc +// ListGitProvidersForUrl godoc // // @Tags gitProvider -// @Summary Get Git provider -// @Description Get Git provider +// @Summary List Git providers for url +// @Description List Git providers for url // @Produce json -// @Param url path string true "Url" -// @Success 200 {object} gitprovider.GitProviderConfig +// @Param url path string true "Url" +// @Success 200 {array} gitprovider.GitProviderConfig // @Router /gitprovider/for-url/{url} [get] // -// @id GetGitProviderForUrl -func GetGitProviderForUrl(ctx *gin.Context) { +// @id ListGitProvidersForUrl +func ListGitProvidersForUrl(ctx *gin.Context) { urlParam := ctx.Param("url") decodedUrl, err := url.QueryUnescape(urlParam) @@ -68,12 +69,48 @@ func GetGitProviderForUrl(ctx *gin.Context) { server := server.GetInstance(nil) - gitProvider, err := server.GitProviderService.GetConfigForUrl(decodedUrl) + gitProviders, err := server.GitProviderService.ListConfigsForUrl(decodedUrl) if err != nil { ctx.AbortWithError(http.StatusInternalServerError, fmt.Errorf("failed to get git provider for url: %w", err)) return } + apiKeyType, ok := ctx.Get("apiKeyType") + if !ok || apiKeyType == apikey.ApiKeyTypeClient { + for _, gitProvider := range gitProviders { + gitProvider.Token = "" + } + } + + ctx.JSON(200, gitProviders) +} + +// GetGitProvider godoc +// +// @Tags gitProvider +// @Summary Get Git provider +// @Description Get Git provider +// @Produce plain +// @Param gitProviderId path string true "ID" +// @Success 200 {object} gitprovider.GitProviderConfig +// @Router /gitprovider/{gitProviderId} [get] +// +// @id GetGitProvider +func GetGitProvider(ctx *gin.Context) { + id := ctx.Param("gitProviderId") + + server := server.GetInstance(nil) + + gitProvider, err := server.GitProviderService.GetConfig(id) + if err != nil { + statusCode, message, codeErr := controllers.GetHTTPStatusCodeAndMessageFromError(err) + if codeErr != nil { + ctx.AbortWithError(statusCode, codeErr) + } + ctx.AbortWithError(statusCode, errors.New(message)) + return + } + ctx.JSON(200, gitProvider) } diff --git a/pkg/api/docs/docs.go b/pkg/api/docs/docs.go index 8a3d822c45..73be40e1a5 100644 --- a/pkg/api/docs/docs.go +++ b/pkg/api/docs/docs.go @@ -478,15 +478,15 @@ const docTemplate = `{ }, "/gitprovider/for-url/{url}": { "get": { - "description": "Get Git provider", + "description": "List Git providers for url", "produces": [ "application/json" ], "tags": [ "gitProvider" ], - "summary": "Get Git provider", - "operationId": "GetGitProviderForUrl", + "summary": "List Git providers for url", + "operationId": "ListGitProvidersForUrl", "parameters": [ { "type": "string", @@ -500,7 +500,10 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/GitProvider" + "type": "array", + "items": { + "$ref": "#/definitions/GitProvider" + } } } } @@ -537,6 +540,34 @@ const docTemplate = `{ } }, "/gitprovider/{gitProviderId}": { + "get": { + "description": "Get Git provider", + "produces": [ + "text/plain" + ], + "tags": [ + "gitProvider" + ], + "summary": "Get Git provider", + "operationId": "GetGitProvider", + "parameters": [ + { + "type": "string", + "description": "ID", + "name": "gitProviderId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/GitProvider" + } + } + } + }, "delete": { "description": "Remove Git provider", "produces": [ diff --git a/pkg/api/docs/swagger.json b/pkg/api/docs/swagger.json index b37e2e7abe..074231de34 100644 --- a/pkg/api/docs/swagger.json +++ b/pkg/api/docs/swagger.json @@ -475,15 +475,15 @@ }, "/gitprovider/for-url/{url}": { "get": { - "description": "Get Git provider", + "description": "List Git providers for url", "produces": [ "application/json" ], "tags": [ "gitProvider" ], - "summary": "Get Git provider", - "operationId": "GetGitProviderForUrl", + "summary": "List Git providers for url", + "operationId": "ListGitProvidersForUrl", "parameters": [ { "type": "string", @@ -497,7 +497,10 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/GitProvider" + "type": "array", + "items": { + "$ref": "#/definitions/GitProvider" + } } } } @@ -534,6 +537,34 @@ } }, "/gitprovider/{gitProviderId}": { + "get": { + "description": "Get Git provider", + "produces": [ + "text/plain" + ], + "tags": [ + "gitProvider" + ], + "summary": "Get Git provider", + "operationId": "GetGitProvider", + "parameters": [ + { + "type": "string", + "description": "ID", + "name": "gitProviderId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/GitProvider" + } + } + } + }, "delete": { "description": "Remove Git provider", "produces": [ diff --git a/pkg/api/docs/swagger.yaml b/pkg/api/docs/swagger.yaml index b683928ced..6762a3125f 100644 --- a/pkg/api/docs/swagger.yaml +++ b/pkg/api/docs/swagger.yaml @@ -1142,6 +1142,25 @@ paths: summary: Remove Git provider tags: - gitProvider + get: + description: Get Git provider + operationId: GetGitProvider + parameters: + - description: ID + in: path + name: gitProviderId + required: true + type: string + produces: + - text/plain + responses: + "200": + description: OK + schema: + $ref: '#/definitions/GitProvider' + summary: Get Git provider + tags: + - gitProvider /gitprovider/{gitProviderId}/{namespaceId}/{repositoryId}/branches: get: description: Get Git repository branches @@ -1351,8 +1370,8 @@ paths: - gitProvider /gitprovider/for-url/{url}: get: - description: Get Git provider - operationId: GetGitProviderForUrl + description: List Git providers for url + operationId: ListGitProvidersForUrl parameters: - description: Url in: path @@ -1365,8 +1384,10 @@ paths: "200": description: OK schema: - $ref: '#/definitions/GitProvider' - summary: Get Git provider + items: + $ref: '#/definitions/GitProvider' + type: array + summary: List Git providers for url tags: - gitProvider /gitprovider/id-for-url/{url}: diff --git a/pkg/api/middlewares/auth.go b/pkg/api/middlewares/auth.go index e100356088..441b7144ec 100644 --- a/pkg/api/middlewares/auth.go +++ b/pkg/api/middlewares/auth.go @@ -7,6 +7,7 @@ import ( "errors" "strings" + "github.com/daytonaio/daytona/pkg/apikey" "github.com/daytonaio/daytona/pkg/server" "github.com/gin-gonic/gin" ) @@ -29,8 +30,18 @@ func AuthMiddleware() gin.HandlerFunc { if !server.ApiKeyService.IsValidApiKey(token) { ctx.AbortWithError(401, errors.New("unauthorized")) + return + } + + apiKeyType := apikey.ApiKeyTypeClient + + if server.ApiKeyService.IsWorkspaceApiKey(token) { + apiKeyType = apikey.ApiKeyTypeWorkspace + } else if server.ApiKeyService.IsProjectApiKey(token) { + apiKeyType = apikey.ApiKeyTypeProject } + ctx.Set("apiKeyType", apiKeyType) ctx.Next() } } diff --git a/pkg/api/server.go b/pkg/api/server.go index 421a2f655d..c341fe7607 100644 --- a/pkg/api/server.go +++ b/pkg/api/server.go @@ -231,6 +231,7 @@ func (a *ApiServer) Start() error { gitProviderController.GET("/:gitProviderId/:namespaceId/:repositoryId/pull-requests", gitprovider.GetRepoPRs) gitProviderController.POST("/context", gitprovider.GetGitContext) gitProviderController.POST("/context/url", gitprovider.GetUrlFromRepository) + gitProviderController.GET("/for-url/:url", gitprovider.ListGitProvidersForUrl) gitProviderController.GET("/id-for-url/:url", gitprovider.GetGitProviderIdForUrl) } @@ -257,7 +258,7 @@ func (a *ApiServer) Start() error { projectGroup.Use(middlewares.ProjectAuthMiddleware()) { projectGroup.POST(workspaceController.BasePath()+"/:workspaceId/:projectId/state", workspace.SetProjectState) - projectGroup.GET(gitProviderController.BasePath()+"/for-url/:url", gitprovider.GetGitProviderForUrl) + projectGroup.GET(gitProviderController.BasePath()+"/:gitProviderId", gitprovider.GetGitProvider) } a.httpServer = &http.Server{ diff --git a/pkg/apiclient/README.md b/pkg/apiclient/README.md index b7320730fe..a9f9f4a69e 100644 --- a/pkg/apiclient/README.md +++ b/pkg/apiclient/README.md @@ -92,7 +92,7 @@ Class | Method | HTTP request | Description *ContainerRegistryAPI* | [**SetContainerRegistry**](docs/ContainerRegistryAPI.md#setcontainerregistry) | **Put** /container-registry/{server} | Set container registry credentials *DefaultAPI* | [**HealthCheck**](docs/DefaultAPI.md#healthcheck) | **Get** /health | Health check *GitProviderAPI* | [**GetGitContext**](docs/GitProviderAPI.md#getgitcontext) | **Post** /gitprovider/context | Get Git context -*GitProviderAPI* | [**GetGitProviderForUrl**](docs/GitProviderAPI.md#getgitproviderforurl) | **Get** /gitprovider/for-url/{url} | Get Git provider +*GitProviderAPI* | [**GetGitProvider**](docs/GitProviderAPI.md#getgitprovider) | **Get** /gitprovider/{gitProviderId} | Get Git provider *GitProviderAPI* | [**GetGitProviderIdForUrl**](docs/GitProviderAPI.md#getgitprovideridforurl) | **Get** /gitprovider/id-for-url/{url} | Get Git provider ID *GitProviderAPI* | [**GetGitUser**](docs/GitProviderAPI.md#getgituser) | **Get** /gitprovider/{gitProviderId}/user | Get Git context *GitProviderAPI* | [**GetNamespaces**](docs/GitProviderAPI.md#getnamespaces) | **Get** /gitprovider/{gitProviderId}/namespaces | Get Git namespaces @@ -101,6 +101,7 @@ Class | Method | HTTP request | Description *GitProviderAPI* | [**GetRepositories**](docs/GitProviderAPI.md#getrepositories) | **Get** /gitprovider/{gitProviderId}/{namespaceId}/repositories | Get Git repositories *GitProviderAPI* | [**GetUrlFromRepository**](docs/GitProviderAPI.md#geturlfromrepository) | **Post** /gitprovider/context/url | Get URL from Git repository *GitProviderAPI* | [**ListGitProviders**](docs/GitProviderAPI.md#listgitproviders) | **Get** /gitprovider | List Git providers +*GitProviderAPI* | [**ListGitProvidersForUrl**](docs/GitProviderAPI.md#listgitprovidersforurl) | **Get** /gitprovider/for-url/{url} | List Git providers for url *GitProviderAPI* | [**RemoveGitProvider**](docs/GitProviderAPI.md#removegitprovider) | **Delete** /gitprovider/{gitProviderId} | Remove Git provider *GitProviderAPI* | [**SetGitProvider**](docs/GitProviderAPI.md#setgitprovider) | **Put** /gitprovider | Set Git provider *PrebuildAPI* | [**DeletePrebuild**](docs/PrebuildAPI.md#deleteprebuild) | **Delete** /project-config/{configName}/prebuild/{prebuildId} | Delete prebuild diff --git a/pkg/apiclient/api/openapi.yaml b/pkg/apiclient/api/openapi.yaml index 5fe4006448..a2d386d6c5 100644 --- a/pkg/apiclient/api/openapi.yaml +++ b/pkg/apiclient/api/openapi.yaml @@ -341,8 +341,8 @@ paths: x-codegen-request-body-name: repository /gitprovider/for-url/{url}: get: - description: Get Git provider - operationId: GetGitProviderForUrl + description: List Git providers for url + operationId: ListGitProvidersForUrl parameters: - description: Url in: path @@ -355,9 +355,11 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/GitProvider' + items: + $ref: '#/components/schemas/GitProvider' + type: array description: OK - summary: Get Git provider + summary: List Git providers for url tags: - gitProvider /gitprovider/id-for-url/{url}: @@ -399,6 +401,26 @@ paths: summary: Remove Git provider tags: - gitProvider + get: + description: Get Git provider + operationId: GetGitProvider + parameters: + - description: ID + in: path + name: gitProviderId + required: true + schema: + type: string + responses: + "200": + content: + text/plain: + schema: + $ref: '#/components/schemas/GitProvider' + description: OK + summary: Get Git provider + tags: + - gitProvider /gitprovider/{gitProviderId}/namespaces: get: description: Get Git namespaces diff --git a/pkg/apiclient/api_git_provider.go b/pkg/apiclient/api_git_provider.go index f007895f29..aba377926a 100644 --- a/pkg/apiclient/api_git_provider.go +++ b/pkg/apiclient/api_git_provider.go @@ -148,37 +148,37 @@ func (a *GitProviderAPIService) GetGitContextExecute(r ApiGetGitContextRequest) return localVarReturnValue, localVarHTTPResponse, nil } -type ApiGetGitProviderForUrlRequest struct { - ctx context.Context - ApiService *GitProviderAPIService - url string +type ApiGetGitProviderRequest struct { + ctx context.Context + ApiService *GitProviderAPIService + gitProviderId string } -func (r ApiGetGitProviderForUrlRequest) Execute() (*GitProvider, *http.Response, error) { - return r.ApiService.GetGitProviderForUrlExecute(r) +func (r ApiGetGitProviderRequest) Execute() (*GitProvider, *http.Response, error) { + return r.ApiService.GetGitProviderExecute(r) } /* -GetGitProviderForUrl Get Git provider +GetGitProvider Get Git provider Get Git provider @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param url Url - @return ApiGetGitProviderForUrlRequest + @param gitProviderId ID + @return ApiGetGitProviderRequest */ -func (a *GitProviderAPIService) GetGitProviderForUrl(ctx context.Context, url string) ApiGetGitProviderForUrlRequest { - return ApiGetGitProviderForUrlRequest{ - ApiService: a, - ctx: ctx, - url: url, +func (a *GitProviderAPIService) GetGitProvider(ctx context.Context, gitProviderId string) ApiGetGitProviderRequest { + return ApiGetGitProviderRequest{ + ApiService: a, + ctx: ctx, + gitProviderId: gitProviderId, } } // Execute executes the request // // @return GitProvider -func (a *GitProviderAPIService) GetGitProviderForUrlExecute(r ApiGetGitProviderForUrlRequest) (*GitProvider, *http.Response, error) { +func (a *GitProviderAPIService) GetGitProviderExecute(r ApiGetGitProviderRequest) (*GitProvider, *http.Response, error) { var ( localVarHTTPMethod = http.MethodGet localVarPostBody interface{} @@ -186,13 +186,13 @@ func (a *GitProviderAPIService) GetGitProviderForUrlExecute(r ApiGetGitProviderF localVarReturnValue *GitProvider ) - localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "GitProviderAPIService.GetGitProviderForUrl") + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "GitProviderAPIService.GetGitProvider") if err != nil { return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} } - localVarPath := localBasePath + "/gitprovider/for-url/{url}" - localVarPath = strings.Replace(localVarPath, "{"+"url"+"}", url.PathEscape(parameterValueToString(r.url, "url")), -1) + localVarPath := localBasePath + "/gitprovider/{gitProviderId}" + localVarPath = strings.Replace(localVarPath, "{"+"gitProviderId"+"}", url.PathEscape(parameterValueToString(r.gitProviderId, "gitProviderId")), -1) localVarHeaderParams := make(map[string]string) localVarQueryParams := url.Values{} @@ -208,7 +208,7 @@ func (a *GitProviderAPIService) GetGitProviderForUrlExecute(r ApiGetGitProviderF } // to determine the Accept header - localVarHTTPHeaderAccepts := []string{"application/json"} + localVarHTTPHeaderAccepts := []string{"text/plain"} // set Accept header localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) @@ -1314,6 +1314,124 @@ func (a *GitProviderAPIService) ListGitProvidersExecute(r ApiListGitProvidersReq return localVarReturnValue, localVarHTTPResponse, nil } +type ApiListGitProvidersForUrlRequest struct { + ctx context.Context + ApiService *GitProviderAPIService + url string +} + +func (r ApiListGitProvidersForUrlRequest) Execute() ([]GitProvider, *http.Response, error) { + return r.ApiService.ListGitProvidersForUrlExecute(r) +} + +/* +ListGitProvidersForUrl List Git providers for url + +List Git providers for url + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param url Url + @return ApiListGitProvidersForUrlRequest +*/ +func (a *GitProviderAPIService) ListGitProvidersForUrl(ctx context.Context, url string) ApiListGitProvidersForUrlRequest { + return ApiListGitProvidersForUrlRequest{ + ApiService: a, + ctx: ctx, + url: url, + } +} + +// Execute executes the request +// +// @return []GitProvider +func (a *GitProviderAPIService) ListGitProvidersForUrlExecute(r ApiListGitProvidersForUrlRequest) ([]GitProvider, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue []GitProvider + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "GitProviderAPIService.ListGitProvidersForUrl") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/gitprovider/for-url/{url}" + localVarPath = strings.Replace(localVarPath, "{"+"url"+"}", url.PathEscape(parameterValueToString(r.url, "url")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.ctx != nil { + // API Key Authentication + if auth, ok := r.ctx.Value(ContextAPIKeys).(map[string]APIKey); ok { + if apiKey, ok := auth["Bearer"]; ok { + var key string + if apiKey.Prefix != "" { + key = apiKey.Prefix + " " + apiKey.Key + } else { + key = apiKey.Key + } + localVarHeaderParams["Authorization"] = key + } + } + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := io.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + type ApiRemoveGitProviderRequest struct { ctx context.Context ApiService *GitProviderAPIService diff --git a/pkg/apiclient/docs/GitProviderAPI.md b/pkg/apiclient/docs/GitProviderAPI.md index 622e355e06..2fa81645cd 100644 --- a/pkg/apiclient/docs/GitProviderAPI.md +++ b/pkg/apiclient/docs/GitProviderAPI.md @@ -5,7 +5,7 @@ All URIs are relative to *http://localhost:3986* Method | HTTP request | Description ------------- | ------------- | ------------- [**GetGitContext**](GitProviderAPI.md#GetGitContext) | **Post** /gitprovider/context | Get Git context -[**GetGitProviderForUrl**](GitProviderAPI.md#GetGitProviderForUrl) | **Get** /gitprovider/for-url/{url} | Get Git provider +[**GetGitProvider**](GitProviderAPI.md#GetGitProvider) | **Get** /gitprovider/{gitProviderId} | Get Git provider [**GetGitProviderIdForUrl**](GitProviderAPI.md#GetGitProviderIdForUrl) | **Get** /gitprovider/id-for-url/{url} | Get Git provider ID [**GetGitUser**](GitProviderAPI.md#GetGitUser) | **Get** /gitprovider/{gitProviderId}/user | Get Git context [**GetNamespaces**](GitProviderAPI.md#GetNamespaces) | **Get** /gitprovider/{gitProviderId}/namespaces | Get Git namespaces @@ -14,6 +14,7 @@ Method | HTTP request | Description [**GetRepositories**](GitProviderAPI.md#GetRepositories) | **Get** /gitprovider/{gitProviderId}/{namespaceId}/repositories | Get Git repositories [**GetUrlFromRepository**](GitProviderAPI.md#GetUrlFromRepository) | **Post** /gitprovider/context/url | Get URL from Git repository [**ListGitProviders**](GitProviderAPI.md#ListGitProviders) | **Get** /gitprovider | List Git providers +[**ListGitProvidersForUrl**](GitProviderAPI.md#ListGitProvidersForUrl) | **Get** /gitprovider/for-url/{url} | List Git providers for url [**RemoveGitProvider**](GitProviderAPI.md#RemoveGitProvider) | **Delete** /gitprovider/{gitProviderId} | Remove Git provider [**SetGitProvider**](GitProviderAPI.md#SetGitProvider) | **Put** /gitprovider | Set Git provider @@ -85,9 +86,9 @@ Name | Type | Description | Notes [[Back to README]](../README.md) -## GetGitProviderForUrl +## GetGitProvider -> GitProvider GetGitProviderForUrl(ctx, url).Execute() +> GitProvider GetGitProvider(ctx, gitProviderId).Execute() Get Git provider @@ -106,17 +107,17 @@ import ( ) func main() { - url := "url_example" // string | Url + gitProviderId := "gitProviderId_example" // string | ID configuration := openapiclient.NewConfiguration() apiClient := openapiclient.NewAPIClient(configuration) - resp, r, err := apiClient.GitProviderAPI.GetGitProviderForUrl(context.Background(), url).Execute() + resp, r, err := apiClient.GitProviderAPI.GetGitProvider(context.Background(), gitProviderId).Execute() if err != nil { - fmt.Fprintf(os.Stderr, "Error when calling `GitProviderAPI.GetGitProviderForUrl``: %v\n", err) + fmt.Fprintf(os.Stderr, "Error when calling `GitProviderAPI.GetGitProvider``: %v\n", err) fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r) } - // response from `GetGitProviderForUrl`: GitProvider - fmt.Fprintf(os.Stdout, "Response from `GitProviderAPI.GetGitProviderForUrl`: %v\n", resp) + // response from `GetGitProvider`: GitProvider + fmt.Fprintf(os.Stdout, "Response from `GitProviderAPI.GetGitProvider`: %v\n", resp) } ``` @@ -126,11 +127,11 @@ func main() { Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- **ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. -**url** | **string** | Url | +**gitProviderId** | **string** | ID | ### Other Parameters -Other parameters are passed through a pointer to a apiGetGitProviderForUrlRequest struct via the builder pattern +Other parameters are passed through a pointer to a apiGetGitProviderRequest struct via the builder pattern Name | Type | Description | Notes @@ -148,7 +149,7 @@ Name | Type | Description | Notes ### HTTP request headers - **Content-Type**: Not defined -- **Accept**: application/json +- **Accept**: text/plain [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) @@ -733,6 +734,76 @@ Other parameters are passed through a pointer to a apiListGitProvidersRequest st [[Back to README]](../README.md) +## ListGitProvidersForUrl + +> []GitProvider ListGitProvidersForUrl(ctx, url).Execute() + +List Git providers for url + + + +### Example + +```go +package main + +import ( + "context" + "fmt" + "os" + openapiclient "github.com/GIT_USER_ID/GIT_REPO_ID/apiclient" +) + +func main() { + url := "url_example" // string | Url + + configuration := openapiclient.NewConfiguration() + apiClient := openapiclient.NewAPIClient(configuration) + resp, r, err := apiClient.GitProviderAPI.ListGitProvidersForUrl(context.Background(), url).Execute() + if err != nil { + fmt.Fprintf(os.Stderr, "Error when calling `GitProviderAPI.ListGitProvidersForUrl``: %v\n", err) + fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r) + } + // response from `ListGitProvidersForUrl`: []GitProvider + fmt.Fprintf(os.Stdout, "Response from `GitProviderAPI.ListGitProvidersForUrl`: %v\n", resp) +} +``` + +### Path Parameters + + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- +**ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. +**url** | **string** | Url | + +### Other Parameters + +Other parameters are passed through a pointer to a apiListGitProvidersForUrlRequest struct via the builder pattern + + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + + +### Return type + +[**[]GitProvider**](GitProvider.md) + +### Authorization + +[Bearer](../README.md#Bearer) + +### HTTP request headers + +- **Content-Type**: Not defined +- **Accept**: application/json + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) +[[Back to Model list]](../README.md#documentation-for-models) +[[Back to README]](../README.md) + + ## RemoveGitProvider > RemoveGitProvider(ctx, gitProviderId).Execute() diff --git a/pkg/build/mocks/gitprovider_config_store.go b/pkg/build/mocks/gitprovider_config_store.go index de477f0244..46f18054ef 100644 --- a/pkg/build/mocks/gitprovider_config_store.go +++ b/pkg/build/mocks/gitprovider_config_store.go @@ -12,7 +12,7 @@ type MockGitProviderConfigStore struct { mock.Mock } -func (s *MockGitProviderConfigStore) GetConfigForUrl(url string) (*gitprovider.GitProviderConfig, error) { +func (s *MockGitProviderConfigStore) ListConfigsForUrl(url string) ([]*gitprovider.GitProviderConfig, error) { args := s.Called(url) - return args.Get(0).(*gitprovider.GitProviderConfig), args.Error(1) + return args.Get(0).([]*gitprovider.GitProviderConfig), args.Error(1) } diff --git a/pkg/build/runner.go b/pkg/build/runner.go index b81ae73e8d..d73b6a6d1d 100644 --- a/pkg/build/runner.go +++ b/pkg/build/runner.go @@ -60,7 +60,7 @@ type BuildProcessConfig struct { } type GitProviderStore interface { - GetConfigForUrl(url string) (*gitprovider.GitProviderConfig, error) + ListConfigsForUrl(url string) ([]*gitprovider.GitProviderConfig, error) } func NewBuildRunner(config BuildRunnerInstanceConfig) *BuildRunner { @@ -240,17 +240,17 @@ func (r *BuildRunner) RunBuildProcess(config BuildProcessConfig) { return } - gitProvider, err := r.gitProviderStore.GetConfigForUrl(config.Build.Repository.Url) - if err != nil && !gitprovider.IsGitProviderNotFound(err) { + gitProviders, err := r.gitProviderStore.ListConfigsForUrl(config.Build.Repository.Url) + if err != nil { r.handleBuildError(*config.Build, config.Builder, err, config.BuildLogger) return } var auth *http.BasicAuth - if gitProvider != nil { + if len(gitProviders) > 0 { auth = &http.BasicAuth{} - auth.Username = gitProvider.Username - auth.Password = gitProvider.Token + auth.Username = gitProviders[0].Username + auth.Password = gitProviders[0].Token } err = config.GitService.CloneRepository(config.Build.Repository, auth) diff --git a/pkg/build/runner_test.go b/pkg/build/runner_test.go index 92c3de72ec..47454ddbd2 100644 --- a/pkg/build/runner_test.go +++ b/pkg/build/runner_test.go @@ -103,7 +103,7 @@ func (s *BuildRunnerTestSuite) TestRun() { func (s *BuildRunnerTestSuite) TestRunBuildProcess() { pendingBuild := *mocks.MockBuild - s.mockGitProviderConfigStore.On("GetConfigForUrl", pendingBuild.Repository.Url).Return(&gitProviderConfig, nil) + s.mockGitProviderConfigStore.On("ListConfigsForUrl", pendingBuild.Repository.Url).Return([]*gitprovider.GitProviderConfig{&gitProviderConfig}, nil) s.mockGitService.On("CloneRepository", pendingBuild.Repository, &http.BasicAuth{ Username: gitProviderConfig.Username, }).Return(nil) diff --git a/pkg/cmd/workspace/create.go b/pkg/cmd/workspace/create.go index 0710c57c3a..c86884b72e 100644 --- a/pkg/cmd/workspace/create.go +++ b/pkg/cmd/workspace/create.go @@ -22,6 +22,7 @@ import ( "github.com/daytonaio/daytona/pkg/common" "github.com/daytonaio/daytona/pkg/logs" "github.com/daytonaio/daytona/pkg/views" + gitprovider_view "github.com/daytonaio/daytona/pkg/views/gitprovider" logs_view "github.com/daytonaio/daytona/pkg/views/logs" views_util "github.com/daytonaio/daytona/pkg/views/util" "github.com/daytonaio/daytona/pkg/views/workspace/create" @@ -413,6 +414,21 @@ func processGitURL(ctx context.Context, repoUrl string, apiClient *apiclient.API return nil, err } + gitProviderConfigs, res, err := apiClient.GitProviderAPI.ListGitProvidersForUrl(context.Background(), url.QueryEscape(repoUrl)).Execute() + if err != nil { + return nil, apiclient_util.HandleErrorResponse(res, err) + } + + if len(gitProviderConfigs) == 1 { + projectConfigurationFlags.GitProviderConfig = &gitProviderConfigs[0].Id + } else if len(gitProviderConfigs) > 1 { + gp, err := gitprovider_view.GetGitProviderFromPrompt(context.Background(), gitProviderConfigs, apiClient) + if err != nil { + return nil, err + } + projectConfigurationFlags.GitProviderConfig = &gp.Id + } + project, err := workspace_util.GetCreateProjectDtoFromFlags(projectConfigurationFlags) if err != nil { return nil, err diff --git a/pkg/cmd/workspace/util/creation_data.go b/pkg/cmd/workspace/util/creation_data.go index 23022757f9..106800e44d 100644 --- a/pkg/cmd/workspace/util/creation_data.go +++ b/pkg/cmd/workspace/util/creation_data.go @@ -17,6 +17,7 @@ import ( apiclient_util "github.com/daytonaio/daytona/internal/util/apiclient" "github.com/daytonaio/daytona/pkg/apiclient" "github.com/daytonaio/daytona/pkg/common" + gitprovider_view "github.com/daytonaio/daytona/pkg/views/gitprovider" views_util "github.com/daytonaio/daytona/pkg/views/util" "github.com/daytonaio/daytona/pkg/views/workspace/create" "github.com/daytonaio/daytona/pkg/views/workspace/selection" @@ -124,7 +125,7 @@ func GetProjectsCreationDataFromPrompt(config ProjectsDataPromptConfig) ([]apicl } } - providerRepo, err := getRepositoryFromWizard(RepositoryWizardConfig{ + providerRepo, gitProviderConfigId, err := getRepositoryFromWizard(RepositoryWizardConfig{ ApiClient: config.ApiClient, UserGitProviders: config.UserGitProviders, Manual: config.Manual, @@ -137,6 +138,23 @@ func GetProjectsCreationDataFromPrompt(config ProjectsDataPromptConfig) ([]apicl return nil, err } + if gitProviderConfigId == selection.CustomRepoIdentifier || gitProviderConfigId == selection.CREATE_FROM_SAMPLE { + gitProviderConfigs, res, err := config.ApiClient.GitProviderAPI.ListGitProvidersForUrl(context.Background(), url.QueryEscape(providerRepo.Url)).Execute() + if err != nil { + return nil, apiclient_util.HandleErrorResponse(res, err) + } + + if len(gitProviderConfigs) == 1 { + gitProviderConfigId = gitProviderConfigs[0].Id + } else if len(gitProviderConfigs) > 1 { + gp, err := gitprovider_view.GetGitProviderFromPrompt(context.Background(), gitProviderConfigs, config.ApiClient) + if err != nil { + return nil, err + } + gitProviderConfigId = gp.Id + } + } + getRepoContext := createGetRepoContextFromRepository(providerRepo) var res *http.Response @@ -150,11 +168,6 @@ func GetProjectsCreationDataFromPrompt(config ProjectsDataPromptConfig) ([]apicl return nil, err } - gitProviderConfigId, res, err := config.ApiClient.GitProviderAPI.GetGitProviderIdForUrl(context.Background(), url.QueryEscape(providerRepo.Url)).Execute() - if err != nil { - return nil, apiclient_util.HandleErrorResponse(res, err) - } - projectList = append(projectList, newCreateProjectConfigDTO(config, providerRepo, providerRepoName, gitProviderConfigId)) } diff --git a/pkg/cmd/workspace/util/repository_wizard.go b/pkg/cmd/workspace/util/repository_wizard.go index 2b75a5599d..a43cc781de 100644 --- a/pkg/cmd/workspace/util/repository_wizard.go +++ b/pkg/cmd/workspace/util/repository_wizard.go @@ -48,7 +48,7 @@ type RepositoryWizardConfig struct { SelectedRepos map[string]int } -func getRepositoryFromWizard(config RepositoryWizardConfig) (*apiclient.GitRepository, error) { +func getRepositoryFromWizard(config RepositoryWizardConfig) (*apiclient.GitRepository, string, error) { var gitProviderConfigId string var namespaceId string var err error @@ -62,7 +62,7 @@ func getRepositoryFromWizard(config RepositoryWizardConfig) (*apiclient.GitRepos if (len(config.UserGitProviders) == 0 && len(samples) == 0) || config.Manual { repo, err := create.GetRepositoryFromUrlInput(config.MultiProject, config.ProjectOrder, config.ApiClient, config.SelectedRepos) - return repo, err + return repo, selection.CustomRepoIdentifier, err } supportedProviders := config_const.GetSupportedGitProviders() @@ -86,28 +86,28 @@ func getRepositoryFromWizard(config RepositoryWizardConfig) (*apiclient.GitRepos gitProviderConfigId = selection.GetProviderIdFromPrompt(gitProviderViewList, config.ProjectOrder, len(samples) > 0) if gitProviderConfigId == "" { - return nil, common.ErrCtrlCAbort + return nil, "", common.ErrCtrlCAbort } if gitProviderConfigId == selection.CustomRepoIdentifier { repo, err := create.GetRepositoryFromUrlInput(config.MultiProject, config.ProjectOrder, config.ApiClient, config.SelectedRepos) - return repo, err + return repo, selection.CustomRepoIdentifier, err } if gitProviderConfigId == selection.CREATE_FROM_SAMPLE { sample := selection.GetSampleFromPrompt(samples) if sample == nil { - return nil, common.ErrCtrlCAbort + return nil, "", common.ErrCtrlCAbort } repo, res, err := config.ApiClient.GitProviderAPI.GetGitContext(ctx).Repository(apiclient.GetRepositoryContext{ Url: sample.GitUrl, }).Execute() if err != nil { - return nil, apiclient_util.HandleErrorResponse(res, err) + return nil, "", apiclient_util.HandleErrorResponse(res, err) } - return repo, nil + return repo, selection.CREATE_FROM_SAMPLE, nil } var providerId string @@ -140,7 +140,7 @@ func getRepositoryFromWizard(config RepositoryWizardConfig) (*apiclient.GitRepos }) if err != nil { - return nil, err + return nil, "", err } if len(namespaceList) == 1 { @@ -185,7 +185,7 @@ func getRepositoryFromWizard(config RepositoryWizardConfig) (*apiclient.GitRepos break } else { // If user aborts or there's no selection - return nil, common.ErrCtrlCAbort + return nil, "", common.ErrCtrlCAbort } } @@ -209,7 +209,7 @@ func getRepositoryFromWizard(config RepositoryWizardConfig) (*apiclient.GitRepos }) if err != nil { - return nil, err + return nil, "", err } // Check first if the git provider supports pagination @@ -239,15 +239,15 @@ func getRepositoryFromWizard(config RepositoryWizardConfig) (*apiclient.GitRepos break } else { // If user aborts or there's no selection - return nil, common.ErrCtrlCAbort + return nil, "", common.ErrCtrlCAbort } } if config.SkipBranchSelection { - return chosenRepo, nil + return chosenRepo, gitProviderConfigId, nil } - return SetBranchFromWizard(BranchWizardConfig{ + repoWithBranch, err := SetBranchFromWizard(BranchWizardConfig{ ApiClient: config.ApiClient, GitProviderConfigId: gitProviderConfigId, NamespaceId: namespaceId, @@ -256,4 +256,6 @@ func getRepositoryFromWizard(config RepositoryWizardConfig) (*apiclient.GitRepos ProjectOrder: config.ProjectOrder, ProviderId: providerId, }) + + return repoWithBranch, gitProviderConfigId, err } diff --git a/pkg/cmd/workspacemode/git_cred.go b/pkg/cmd/workspacemode/git_cred.go index 1c37d3bbc5..572d9659f8 100644 --- a/pkg/cmd/workspacemode/git_cred.go +++ b/pkg/cmd/workspacemode/git_cred.go @@ -37,15 +37,39 @@ var gitCredCmd = &cobra.Command{ return err } + workspace, res, err := apiClient.WorkspaceAPI.GetWorkspace(ctx, workspaceId).Execute() + if err != nil { + return apiclient.HandleErrorResponse(res, err) + } + + var gitProviderConfigId *string + + for _, project := range workspace.Projects { + if project.Name == projectName { + gitProviderConfigId = project.GitProviderConfigId + break + } + } + + if gitProviderConfigId != nil { + gitProvider, _, _ := apiClient.GitProviderAPI.GetGitProvider(ctx, *gitProviderConfigId).Execute() + if gitProvider != nil { + fmt.Println("username=" + gitProvider.Username) + fmt.Println("password=" + gitProvider.Token) + return nil + } + + } + encodedUrl := url.QueryEscape(host) - gitProvider, _, _ := apiClient.GitProviderAPI.GetGitProviderForUrl(ctx, encodedUrl).Execute() - if gitProvider == nil { + gitProviders, _, _ := apiClient.GitProviderAPI.ListGitProvidersForUrl(ctx, encodedUrl).Execute() + if len(gitProviders) == 0 { fmt.Println("error: git provider not found") os.Exit(1) } - fmt.Println("username=" + gitProvider.Username) - fmt.Println("password=" + gitProvider.Token) + fmt.Println("username=" + gitProviders[0].Username) + fmt.Println("password=" + gitProviders[0].Token) return nil }, } diff --git a/pkg/server/gitproviders/config.go b/pkg/server/gitproviders/config.go new file mode 100644 index 0000000000..0e825f344c --- /dev/null +++ b/pkg/server/gitproviders/config.go @@ -0,0 +1,93 @@ +// Copyright 2024 Daytona Platforms Inc. +// SPDX-License-Identifier: Apache-2.0 + +package gitproviders + +import ( + "net/url" + "strconv" + + "github.com/daytonaio/daytona/pkg/gitprovider" + "github.com/docker/docker/pkg/stringid" +) + +func (s *GitProviderService) GetConfig(id string) (*gitprovider.GitProviderConfig, error) { + return s.configStore.Find(id) +} + +func (s *GitProviderService) ListConfigs() ([]*gitprovider.GitProviderConfig, error) { + return s.configStore.List() +} + +func (s *GitProviderService) ListConfigsForUrl(repoUrl string) ([]*gitprovider.GitProviderConfig, error) { + var gpcs []*gitprovider.GitProviderConfig + + gitProviders, err := s.configStore.List() + if err != nil { + return nil, err + } + + for _, p := range gitProviders { + p.Token = url.QueryEscape(p.Token) + p.Username = url.QueryEscape(p.Username) + + gitProvider, err := s.GetGitProvider(p.Id) + if err != nil { + return nil, err + } + + canHandle, _ := gitProvider.CanHandle(repoUrl) + if canHandle { + _, err = gitProvider.GetRepositoryContext(gitprovider.GetRepositoryContext{ + Url: repoUrl, + }) + if err == nil { + gpcs = append(gpcs, p) + } + } + } + + return gpcs, nil +} + +func (s *GitProviderService) SetGitProviderConfig(providerConfig *gitprovider.GitProviderConfig) error { + gitProvider, err := s.newGitProvider(providerConfig) + if err != nil { + return err + } + + userData, err := gitProvider.GetUser() + if err != nil { + return err + } + providerConfig.Username = userData.Username + if providerConfig.Id == "" { + id := stringid.GenerateRandomID() + id = stringid.TruncateID(id) + providerConfig.Id = id + } + + if providerConfig.Alias == "" { + gitProviderConfigs, err := s.ListConfigs() + if err != nil { + return err + } + + uniqueAlias := userData.Username + aliases := make(map[string]bool) + + for _, c := range gitProviderConfigs { + aliases[c.Alias] = true + } + counter := 2 + + for aliases[uniqueAlias] { + uniqueAlias = userData.Username + strconv.Itoa(counter) + counter++ + } + + providerConfig.Alias = uniqueAlias + } + + return s.configStore.Save(providerConfig) +} diff --git a/pkg/server/gitproviders/gitprovider.go b/pkg/server/gitproviders/gitprovider.go index 4707e176b1..8d2c4ce7ce 100644 --- a/pkg/server/gitproviders/gitprovider.go +++ b/pkg/server/gitproviders/gitprovider.go @@ -7,12 +7,10 @@ import ( "errors" "net/http" "net/url" - "strconv" "strings" "github.com/daytonaio/daytona/cmd/daytona/config" "github.com/daytonaio/daytona/pkg/gitprovider" - "github.com/docker/docker/pkg/stringid" ) func (s *GitProviderService) GetGitProviderForUrl(repoUrl string) (gitprovider.GitProvider, string, error) { @@ -58,45 +56,6 @@ func (s *GitProviderService) GetGitProviderForUrl(repoUrl string) (gitprovider.G return nil, "", errors.New("can not get public client for the URL " + repoUrl) } -func (s *GitProviderService) GetConfigForUrl(repoUrl string) (*gitprovider.GitProviderConfig, error) { - gitProviders, err := s.configStore.List() - if err != nil { - return nil, err - } - - for _, p := range gitProviders { - p.Token = url.QueryEscape(p.Token) - p.Username = url.QueryEscape(p.Username) - - gitProvider, err := s.GetGitProvider(p.Id) - if err != nil { - return nil, err - } - - canHandle, _ := gitProvider.CanHandle(repoUrl) - if canHandle { - _, err = gitProvider.GetRepositoryContext(gitprovider.GetRepositoryContext{ - Url: repoUrl, - }) - if err == nil { - return p, nil - } - } - - } - - supportedGitProviders := config.GetSupportedGitProviders() - for _, provider := range supportedGitProviders { - if strings.Contains(repoUrl, provider.Id) { - return &gitprovider.GitProviderConfig{ - Id: provider.Id, - }, nil - } - } - - return nil, errors.New("git provider not found") -} - func (s *GitProviderService) GetGitProviderForHttpRequest(req *http.Request) (gitprovider.GitProvider, error) { var provider *gitprovider.GitProviderConfig @@ -122,48 +81,6 @@ func (s *GitProviderService) GetGitProviderForHttpRequest(req *http.Request) (gi return s.newGitProvider(provider) } -func (s *GitProviderService) SetGitProviderConfig(providerConfig *gitprovider.GitProviderConfig) error { - gitProvider, err := s.newGitProvider(providerConfig) - if err != nil { - return err - } - - userData, err := gitProvider.GetUser() - if err != nil { - return err - } - providerConfig.Username = userData.Username - if providerConfig.Id == "" { - id := stringid.GenerateRandomID() - id = stringid.TruncateID(id) - providerConfig.Id = id - } - - if providerConfig.Alias == "" { - gitProviderConfigs, err := s.ListConfigs() - if err != nil { - return err - } - - uniqueAlias := userData.Username - aliases := make(map[string]bool) - - for _, c := range gitProviderConfigs { - aliases[c.Alias] = true - } - counter := 2 - - for aliases[uniqueAlias] { - uniqueAlias = userData.Username + strconv.Itoa(counter) - counter++ - } - - providerConfig.Alias = uniqueAlias - } - - return s.configStore.Save(providerConfig) -} - func getHostnameFromUrl(urlToParse string) (string, error) { parsed, err := url.Parse(urlToParse) if err != nil { diff --git a/pkg/server/gitproviders/service.go b/pkg/server/gitproviders/service.go index bc6da98958..bcc735c98a 100644 --- a/pkg/server/gitproviders/service.go +++ b/pkg/server/gitproviders/service.go @@ -14,7 +14,7 @@ import ( type IGitProviderService interface { GetConfig(id string) (*gitprovider.GitProviderConfig, error) - GetConfigForUrl(url string) (*gitprovider.GitProviderConfig, error) + ListConfigsForUrl(url string) ([]*gitprovider.GitProviderConfig, error) GetGitProvider(id string) (gitprovider.GitProvider, error) GetGitProviderForUrl(url string) (gitprovider.GitProvider, string, error) GetGitProviderForHttpRequest(req *http.Request) (gitprovider.GitProvider, error) @@ -68,14 +68,6 @@ func (s *GitProviderService) GetGitProvider(id string) (gitprovider.GitProvider, return s.newGitProvider(providerConfig) } -func (s *GitProviderService) ListConfigs() ([]*gitprovider.GitProviderConfig, error) { - return s.configStore.List() -} - -func (s *GitProviderService) GetConfig(id string) (*gitprovider.GitProviderConfig, error) { - return s.configStore.Find(id) -} - func (s *GitProviderService) GetLastCommitSha(repo *gitprovider.GitRepository) (string, error) { var err error var provider gitprovider.GitProvider diff --git a/pkg/server/workspaces/create.go b/pkg/server/workspaces/create.go index 1797e86fa2..bac065282f 100644 --- a/pkg/server/workspaces/create.go +++ b/pkg/server/workspaces/create.go @@ -79,12 +79,18 @@ func (s *WorkspaceService) CreateWorkspace(ctx context.Context, req dto.CreateWo p.Repository.Url = util.CleanUpRepositoryUrl(p.Repository.Url) if p.GitProviderConfigId == nil || *p.GitProviderConfigId == "" { - _, id, err := s.gitProviderService.GetGitProviderForUrl(p.Repository.Url) + configs, err := s.gitProviderService.ListConfigsForUrl(p.Repository.Url) if err != nil { return nil, err } - p.GitProviderConfigId = &id + if len(configs) > 1 { + return nil, errors.New("multiple git provider configs found for the repository url") + } + + if len(configs) == 1 { + p.GitProviderConfigId = &configs[0].Id + } } if p.Repository.Sha == "" { @@ -161,9 +167,13 @@ func (s *WorkspaceService) createProject(p *project.Project, target *provider.Pr return err } - gc, err := s.gitProviderService.GetConfigForUrl(p.Repository.Url) - if err != nil && !gitprovider.IsGitProviderNotFound(err) { - return err + var gc *gitprovider.GitProviderConfig + + if p.GitProviderConfigId != nil { + gc, err = s.gitProviderService.GetConfig(*p.GitProviderConfigId) + if err != nil && !gitprovider.IsGitProviderNotFound(err) { + return err + } } err = s.provisioner.CreateProject(p, target, cr, gc) diff --git a/pkg/server/workspaces/service_test.go b/pkg/server/workspaces/service_test.go index 583461ba61..1c22e1be87 100644 --- a/pkg/server/workspaces/service_test.go +++ b/pkg/server/workspaces/service_test.go @@ -139,7 +139,7 @@ func TestWorkspaceService(t *testing.T) { provisioner.On("CreateProject", mock.Anything, &target, containerRegistry, &gitProviderConfig).Return(nil) provisioner.On("StartProject", mock.Anything, &target).Return(nil) - gitProviderService.On("GetConfigForUrl", "https://github.com/daytonaio/daytona").Return(&gitProviderConfig, nil) + gitProviderService.On("GetConfig", "github").Return(&gitProviderConfig, nil) workspace, err := service.CreateWorkspace(context.TODO(), createWorkspaceDto) @@ -267,7 +267,7 @@ func TestWorkspaceService(t *testing.T) { apiKeyService.On("Generate", apikey.ApiKeyTypeWorkspace, createWorkspaceDto.Id).Return(createWorkspaceDto.Id, nil) gitProviderService.On("GetLastCommitSha", createWorkspaceDto.Projects[0].Source.Repository).Return("123", nil) - gitProviderService.On("GetConfigForUrl", "https://github.com/daytonaio/daytona").Return(&gitProviderConfig, nil) + gitProviderService.On("ListConfigsForUrl", "https://github.com/daytonaio/daytona").Return([]*gitprovider.GitProviderConfig{&gitProviderConfig}, nil) for _, project := range createWorkspaceDto.Projects { apiKeyService.On("Generate", apikey.ApiKeyTypeProject, fmt.Sprintf("%s/%s", createWorkspaceDto.Id, project.Name)).Return(project.Name, nil)