diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml.action-blocked-by-asf similarity index 100% rename from .github/workflows/codespell.yml rename to .github/workflows/codespell.yml.action-blocked-by-asf diff --git a/backend/plugins/bitbucket/api/connection_api_test.go b/backend/plugins/bitbucket/api/connection_api_test.go index 33b26d857cd..3adaf640a3c 100644 --- a/backend/plugins/bitbucket/api/connection_api_test.go +++ b/backend/plugins/bitbucket/api/connection_api_test.go @@ -206,11 +206,11 @@ func TestMergeFromRequest_HandlesUsesApiToken(t *testing.T) { // After merge, UsesApiToken should be updated // This is a structural test - actual merge logic is in the connection.go MergeFromRequest method assert.True(t, connection.UsesApiToken, "Initial value should be true") - + // If we were to apply the merge: connection.UsesApiToken = newValues["usesApiToken"].(bool) connection.Username = newValues["username"].(string) - + assert.False(t, connection.UsesApiToken, "After merge, should be false") assert.Equal(t, "new_username", connection.Username) } @@ -218,10 +218,10 @@ func TestMergeFromRequest_HandlesUsesApiToken(t *testing.T) { func TestConnectionStatusCodes(t *testing.T) { // Test expected status code handling tests := []struct { - name string - statusCode int - expectedError bool - errorType string + name string + statusCode int + expectedError bool + errorType string }{ { name: "Success - 200 OK", diff --git a/backend/plugins/gh-copilot/models/models_test.go b/backend/plugins/gh-copilot/models/models_test.go index 72ead8a65e9..8c61d222079 100644 --- a/backend/plugins/gh-copilot/models/models_test.go +++ b/backend/plugins/gh-copilot/models/models_test.go @@ -22,24 +22,24 @@ import "testing" func TestGetTablesInfo(t *testing.T) { tables := GetTablesInfo() expected := map[string]bool{ - (&GhCopilotConnection{}).TableName(): false, - (&GhCopilotScope{}).TableName(): false, - (&GhCopilotScopeConfig{}).TableName(): false, - (&GhCopilotOrgMetrics{}).TableName(): false, - (&GhCopilotLanguageMetrics{}).TableName(): false, - (&GhCopilotEnterpriseDailyMetrics{}).TableName(): false, - (&GhCopilotMetricsByIde{}).TableName(): false, - (&GhCopilotMetricsByFeature{}).TableName(): false, - (&GhCopilotMetricsByLanguageFeature{}).TableName(): false, - (&GhCopilotMetricsByLanguageModel{}).TableName(): false, - (&GhCopilotMetricsByModelFeature{}).TableName(): false, - (&GhCopilotUserDailyMetrics{}).TableName(): false, - (&GhCopilotUserMetricsByIde{}).TableName(): false, - (&GhCopilotUserMetricsByFeature{}).TableName(): false, + (&GhCopilotConnection{}).TableName(): false, + (&GhCopilotScope{}).TableName(): false, + (&GhCopilotScopeConfig{}).TableName(): false, + (&GhCopilotOrgMetrics{}).TableName(): false, + (&GhCopilotLanguageMetrics{}).TableName(): false, + (&GhCopilotEnterpriseDailyMetrics{}).TableName(): false, + (&GhCopilotMetricsByIde{}).TableName(): false, + (&GhCopilotMetricsByFeature{}).TableName(): false, + (&GhCopilotMetricsByLanguageFeature{}).TableName(): false, + (&GhCopilotMetricsByLanguageModel{}).TableName(): false, + (&GhCopilotMetricsByModelFeature{}).TableName(): false, + (&GhCopilotUserDailyMetrics{}).TableName(): false, + (&GhCopilotUserMetricsByIde{}).TableName(): false, + (&GhCopilotUserMetricsByFeature{}).TableName(): false, (&GhCopilotUserMetricsByLanguageFeature{}).TableName(): false, - (&GhCopilotUserMetricsByLanguageModel{}).TableName(): false, - (&GhCopilotUserMetricsByModelFeature{}).TableName(): false, - (&GhCopilotSeat{}).TableName(): false, + (&GhCopilotUserMetricsByLanguageModel{}).TableName(): false, + (&GhCopilotUserMetricsByModelFeature{}).TableName(): false, + (&GhCopilotSeat{}).TableName(): false, } if len(tables) != len(expected) { diff --git a/backend/plugins/gh-copilot/models/scope_test.go b/backend/plugins/gh-copilot/models/scope_test.go index 92a83952096..6a3d96a0ec4 100644 --- a/backend/plugins/gh-copilot/models/scope_test.go +++ b/backend/plugins/gh-copilot/models/scope_test.go @@ -136,7 +136,7 @@ func TestGhCopilotScope_BeforeSave_BaselinePeriodDays(t *testing.T) { Id: "test-org", BaselinePeriodDays: tt.input, } - err := s.BeforeSave(nil) + err := s.BeforeSave(nil) if err != nil { t.Errorf("BeforeSave() error = %v, want nil", err) } diff --git a/backend/plugins/github/tasks/cicd_job_convertor_test.go b/backend/plugins/github/tasks/cicd_job_convertor_test.go index 7e3438289ba..715e2c8ab79 100644 --- a/backend/plugins/github/tasks/cicd_job_convertor_test.go +++ b/backend/plugins/github/tasks/cicd_job_convertor_test.go @@ -68,63 +68,63 @@ func BenchmarkGenJobID(b *testing.B) { } func TestConvertJobs_SkipNoStartedAt(t *testing.T) { - job := &models.GithubJob{ - ID: 123, - RunID: 456, - Name: "test-job", - StartedAt: nil, - } - - convert := func(inputRow interface{}) ([]interface{}, error) { - line := inputRow.(*models.GithubJob) - if line.StartedAt == nil { - return nil, nil - } - createdAt := *line.StartedAt - domainJob := &devops.CICDTask{ - Name: line.Name, - TaskDatesInfo: devops.TaskDatesInfo{ - CreatedDate: createdAt, - StartedDate: line.StartedAt, - FinishedDate: line.CompletedAt, - }, - } - return []interface{}{domainJob}, nil - } - - result, err := convert(job) - assert.Nil(t, err) - assert.Nil(t, result) + job := &models.GithubJob{ + ID: 123, + RunID: 456, + Name: "test-job", + StartedAt: nil, + } + + convert := func(inputRow interface{}) ([]interface{}, error) { + line := inputRow.(*models.GithubJob) + if line.StartedAt == nil { + return nil, nil + } + createdAt := *line.StartedAt + domainJob := &devops.CICDTask{ + Name: line.Name, + TaskDatesInfo: devops.TaskDatesInfo{ + CreatedDate: createdAt, + StartedDate: line.StartedAt, + FinishedDate: line.CompletedAt, + }, + } + return []interface{}{domainJob}, nil + } + + result, err := convert(job) + assert.Nil(t, err) + assert.Nil(t, result) } func TestConvertJobs_WithStartedAt(t *testing.T) { - now := time.Now() - job := &models.GithubJob{ - ID: 123, - RunID: 456, - Name: "test-job", - StartedAt: &now, - } - - convert := func(inputRow interface{}) ([]interface{}, error) { - line := inputRow.(*models.GithubJob) - if line.StartedAt == nil { - return nil, nil - } - createdAt := *line.StartedAt - domainJob := &devops.CICDTask{ - Name: line.Name, - TaskDatesInfo: devops.TaskDatesInfo{ - CreatedDate: createdAt, - StartedDate: line.StartedAt, - FinishedDate: line.CompletedAt, - }, - } - return []interface{}{domainJob}, nil - } - - result, err := convert(job) - assert.Nil(t, err) - assert.NotNil(t, result) - assert.Equal(t, "test-job", result[0].(*devops.CICDTask).Name) + now := time.Now() + job := &models.GithubJob{ + ID: 123, + RunID: 456, + Name: "test-job", + StartedAt: &now, + } + + convert := func(inputRow interface{}) ([]interface{}, error) { + line := inputRow.(*models.GithubJob) + if line.StartedAt == nil { + return nil, nil + } + createdAt := *line.StartedAt + domainJob := &devops.CICDTask{ + Name: line.Name, + TaskDatesInfo: devops.TaskDatesInfo{ + CreatedDate: createdAt, + StartedDate: line.StartedAt, + FinishedDate: line.CompletedAt, + }, + } + return []interface{}{domainJob}, nil + } + + result, err := convert(job) + assert.Nil(t, err) + assert.NotNil(t, result) + assert.Equal(t, "test-job", result[0].(*devops.CICDTask).Name) } diff --git a/backend/plugins/jira/tasks/epic_collector_test.go b/backend/plugins/jira/tasks/epic_collector_test.go index 8587f0dc28f..8fd31db9774 100644 --- a/backend/plugins/jira/tasks/epic_collector_test.go +++ b/backend/plugins/jira/tasks/epic_collector_test.go @@ -91,16 +91,16 @@ func TestEpicCollectorBatchSizeLogic(t *testing.T) { t.Run(tt.name, func(t *testing.T) { // Test the batch size logic from CollectEpics function batchSize := 100 - + // Replicate the exact logic from CollectEpics - if strings.EqualFold(string(tt.deploymentType), string(models.DeploymentServer)) && - len(tt.versionNumbers) == 3 && - tt.versionNumbers[0] <= 8 { + if strings.EqualFold(string(tt.deploymentType), string(models.DeploymentServer)) && + len(tt.versionNumbers) == 3 && + tt.versionNumbers[0] <= 8 { batchSize = 1 } if batchSize != tt.expectedBatch { - t.Errorf("Batch size for %s with version %v: got %d, want %d", + t.Errorf("Batch size for %s with version %v: got %d, want %d", tt.deploymentType, tt.versionNumbers, batchSize, tt.expectedBatch) } }) @@ -162,7 +162,7 @@ func TestEpicCollectorDeploymentTypeLogic(t *testing.T) { isServer := strings.EqualFold(string(tt.deploymentType), string(models.DeploymentServer)) if isServer != tt.expectServer { - t.Errorf("Deployment type detection for %s: got isServer=%v, want %v", + t.Errorf("Deployment type detection for %s: got isServer=%v, want %v", tt.deploymentType, isServer, tt.expectServer) } }) @@ -201,7 +201,7 @@ func TestEpicCollectorApiEndpointSelection(t *testing.T) { t.Run(tt.name, func(t *testing.T) { // Test the API endpoint selection logic from CollectEpics function var selectedEndpoint string - + if strings.EqualFold(string(tt.deploymentType), string(models.DeploymentServer)) { selectedEndpoint = "api/2/search" } else { @@ -209,9 +209,9 @@ func TestEpicCollectorApiEndpointSelection(t *testing.T) { } if selectedEndpoint != tt.expectedEndpoint { - t.Errorf("API endpoint selection for %s: got %s, want %s", + t.Errorf("API endpoint selection for %s: got %s, want %s", tt.deploymentType, selectedEndpoint, tt.expectedEndpoint) } }) } -} \ No newline at end of file +} diff --git a/backend/plugins/table_info_test.go b/backend/plugins/table_info_test.go index bf187ee1df1..78ab5d290d0 100644 --- a/backend/plugins/table_info_test.go +++ b/backend/plugins/table_info_test.go @@ -29,11 +29,11 @@ import ( bitbucket "github.com/apache/incubator-devlake/plugins/bitbucket/impl" bitbucket_server "github.com/apache/incubator-devlake/plugins/bitbucket_server/impl" circleci "github.com/apache/incubator-devlake/plugins/circleci/impl" - copilot "github.com/apache/incubator-devlake/plugins/gh-copilot/impl" customize "github.com/apache/incubator-devlake/plugins/customize/impl" dbt "github.com/apache/incubator-devlake/plugins/dbt/impl" dora "github.com/apache/incubator-devlake/plugins/dora/impl" feishu "github.com/apache/incubator-devlake/plugins/feishu/impl" + copilot "github.com/apache/incubator-devlake/plugins/gh-copilot/impl" gitee "github.com/apache/incubator-devlake/plugins/gitee/impl" gitextractor "github.com/apache/incubator-devlake/plugins/gitextractor/impl" github "github.com/apache/incubator-devlake/plugins/github/impl" diff --git a/backend/server/api/api.go b/backend/server/api/api.go index cd66b765a89..82f80ff30a6 100644 --- a/backend/server/api/api.go +++ b/backend/server/api/api.go @@ -127,8 +127,8 @@ func SetupApiServer(router *gin.Engine) { router.UseRawPath = true // router.UnescapePathValues = false - // Endpoint to proceed database migration - router.GET("/proceed-db-migration", func(ctx *gin.Context) { + // Endpoint to proceed database migration (now requires authentication) + router.GET("/proceed-db-migration", auth.RequireAuth(), func(ctx *gin.Context) { // Execute database migration errors.Must(services.ExecuteMigration()) // Return success response diff --git a/backend/server/api/auth/middleware.go b/backend/server/api/auth/middleware.go index 231f4d5460c..b668de032f6 100644 --- a/backend/server/api/auth/middleware.go +++ b/backend/server/api/auth/middleware.go @@ -34,16 +34,15 @@ import ( // and clear its session even when the cookie has lapsed; both handlers // short-circuit gracefully when no user is set. var publicPaths = map[string]struct{}{ - "/ping": {}, - "/ready": {}, - "/health": {}, - "/version": {}, - "/proceed-db-migration": {}, - PathMethods: {}, - PathLogin: {}, - PathCallback: {}, - PathLogout: {}, - PathUserInfo: {}, + "/ping": {}, + "/ready": {}, + "/health": {}, + "/version": {}, + PathMethods: {}, + PathLogin: {}, + PathCallback: {}, + PathLogout: {}, + PathUserInfo: {}, } func OIDCAuthentication() gin.HandlerFunc { return defaultService.OIDCAuthentication() } diff --git a/backend/test/helper/client.go b/backend/test/helper/client.go index c3855f58956..8e39d6f5b01 100644 --- a/backend/test/helper/client.go +++ b/backend/test/helper/client.go @@ -180,6 +180,7 @@ func ConnectLocalServer(t *testing.T, clientConfig *LocalClientConfig) *DevlakeC api.CreateAndRunApiServer() }) }() + // NOTE: /proceed-db-migration now requires authentication. If AUTH_ENABLED=true, this test must provide credentials. req, err2 := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/proceed-db-migration", addr), nil) require.NoError(t, err2) d.forceSendHttpRequest(100, req, func(err errors.Error) bool {