Skip to content

Commit ba7add5

Browse files
varsistamas-la
authored andcommitted
Fix/circleci column names (#8799)
* fix(circleci): rename created_at to created_date in jobs/workflows Add migration to copy created_at -> created_date and update models/converters. * fix(circleci): update pipeline parsing * test(circleci): add incremental tests for collectors
1 parent 2ab68ae commit ba7add5

17 files changed

Lines changed: 423 additions & 43 deletions
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
/*
2+
Licensed to the Apache Software Foundation (ASF) under one or more
3+
contributor license agreements. See the NOTICE file distributed with
4+
this work for additional information regarding copyright ownership.
5+
The ASF licenses this file to You under the Apache License, Version 2.0
6+
(the "License"); you may not use this file except in compliance with
7+
the License. You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
*/
17+
18+
package e2e
19+
20+
import (
21+
"sort"
22+
"testing"
23+
"time"
24+
25+
"github.com/apache/incubator-devlake/core/dal"
26+
"github.com/apache/incubator-devlake/core/models/common"
27+
"github.com/apache/incubator-devlake/helpers/e2ehelper"
28+
"github.com/apache/incubator-devlake/helpers/pluginhelper/api"
29+
"github.com/apache/incubator-devlake/plugins/circleci/impl"
30+
"github.com/apache/incubator-devlake/plugins/circleci/models"
31+
"github.com/apache/incubator-devlake/plugins/circleci/tasks"
32+
"github.com/stretchr/testify/assert"
33+
)
34+
35+
// TestCircleciWorkflowIncremental verifies that the workflow collector's incremental
36+
// logic correctly filters pipelines by created_date. This is a regression test for
37+
// the created_at -> created_date column rename.
38+
func TestCircleciWorkflowIncremental(t *testing.T) {
39+
var circleci impl.Circleci
40+
41+
dataflowTester := e2ehelper.NewDataFlowTester(t, "circleci", circleci)
42+
taskData := &tasks.CircleciTaskData{
43+
Options: &tasks.CircleciOptions{
44+
ConnectionId: 1,
45+
ProjectSlug: "github/coldgust/coldgust.github.io",
46+
},
47+
RegexEnricher: api.NewRegexEnricher(),
48+
}
49+
50+
// seed pipelines table via extraction
51+
dataflowTester.ImportCsvIntoRawTable("./raw_tables/_raw_circleci_api_pipelines.csv", "_raw_circleci_api_pipelines")
52+
dataflowTester.FlushTabler(&models.CircleciPipeline{})
53+
dataflowTester.Subtask(tasks.ExtractPipelinesMeta, taskData)
54+
55+
// Part 1: verify the SQL query used by BuildInputIterator works with created_date.
56+
// Pipelines #4-10 have created_date > 17:45 — assert the exact IDs returned.
57+
createdAfter := time.Date(2023, 3, 25, 17, 45, 0, 0, time.UTC)
58+
var pipelines []models.CircleciPipeline
59+
assert.Nil(t, dataflowTester.Dal.All(&pipelines,
60+
dal.Where("connection_id = ? AND project_slug = ? AND created_date > ?",
61+
1, "github/coldgust/coldgust.github.io", createdAfter),
62+
))
63+
pipelineIds := make([]string, len(pipelines))
64+
for i, p := range pipelines {
65+
pipelineIds[i] = p.Id
66+
}
67+
sort.Strings(pipelineIds)
68+
assert.Equal(t, []string{
69+
"23622ee4-e150-4920-9d66-81533fa765a4", // pipeline #5
70+
"2c45280f-7fb3-4025-b703-a547c4a94916", // pipeline #4
71+
"70f3eb15-3b94-4f80-b65e-f23f4b74c33a", // pipeline #6
72+
"7fcc1623-edcc-4a76-ad20-cd81aa83519f", // pipeline #9
73+
"866e967d-f826-4470-aed6-fc0c92e98703", // pipeline #7
74+
"afe0cabe-e7ee-4eb7-bf13-bb6170d139f0", // pipeline #8
75+
"d323f088-02fa-4ed5-9696-fc2f89a27150", // pipeline #10
76+
}, pipelineIds)
77+
78+
// Part 2: verify extraction with only the incrementally-collected workflow raw data
79+
// (workflows for pipelines #4-9 only).
80+
dataflowTester.ImportCsvIntoRawTable("./raw_tables/_raw_circleci_api_workflows_incremental.csv", "_raw_circleci_api_workflows")
81+
dataflowTester.FlushTabler(&models.CircleciWorkflow{})
82+
dataflowTester.Subtask(tasks.ExtractWorkflowsMeta, taskData)
83+
dataflowTester.VerifyTableWithOptions(
84+
models.CircleciWorkflow{},
85+
e2ehelper.TableOptions{
86+
CSVRelPath: "./snapshot_tables/_tool_circleci_workflows_incremental.csv",
87+
IgnoreTypes: []interface{}{common.NoPKModel{}},
88+
IgnoreFields: []string{"started_at", "stopped_at"},
89+
},
90+
)
91+
}
92+
93+
// TestCircleciJobIncremental verifies that the job collector's incremental logic
94+
// correctly filters workflows by created_date. Regression test for the column rename.
95+
func TestCircleciJobIncremental(t *testing.T) {
96+
var circleci impl.Circleci
97+
98+
dataflowTester := e2ehelper.NewDataFlowTester(t, "circleci", circleci)
99+
taskData := &tasks.CircleciTaskData{
100+
Options: &tasks.CircleciOptions{
101+
ConnectionId: 1,
102+
ProjectSlug: "github/coldgust/coldgust.github.io",
103+
},
104+
RegexEnricher: api.NewRegexEnricher(),
105+
Project: &models.CircleciProject{
106+
Id: "abcd",
107+
},
108+
}
109+
110+
// seed workflows table via extraction (all 10 workflows including b3b77371 with null created_date)
111+
dataflowTester.ImportCsvIntoRawTable("./raw_tables/_raw_circleci_api_workflows.csv", "_raw_circleci_api_workflows")
112+
dataflowTester.FlushTabler(&models.CircleciWorkflow{})
113+
dataflowTester.Subtask(tasks.ExtractWorkflowsMeta, taskData)
114+
115+
// Part 1: verify the SQL query used by BuildInputIterator works with created_date.
116+
// Workflows for pipelines #4-9 have created_date > 17:45 — assert the exact IDs returned.
117+
// Workflow b3b77371 (null created_date) is excluded by the > comparison.
118+
createdAfter := time.Date(2023, 3, 25, 17, 45, 0, 0, time.UTC)
119+
var workflows []models.CircleciWorkflow
120+
assert.Nil(t, dataflowTester.Dal.All(&workflows,
121+
dal.Where("connection_id = ? AND project_slug = ? AND created_date > ?",
122+
1, "github/coldgust/coldgust.github.io", createdAfter),
123+
))
124+
workflowIds := make([]string, len(workflows))
125+
for i, w := range workflows {
126+
workflowIds[i] = w.Id
127+
}
128+
sort.Strings(workflowIds)
129+
assert.Equal(t, []string{
130+
"6731159f-5275-4bfa-ba70-39d343d63814", // pipeline #5
131+
"7370985a-9de3-4a47-acbc-e6a1fe8e5812", // pipeline #7
132+
"b9ab7bbe-2f30-4c59-b4e2-eb2005bffb14", // pipeline #6
133+
"c7df82a6-0d2b-4e19-a36a-3f3aa9fd3943", // pipeline #4
134+
"fc76deef-bcdd-4856-8e96-a8e2d1c5a85f", // pipeline #8
135+
"fd0bd4f5-264f-4e3c-a151-06153c018f78", // pipeline #9
136+
}, workflowIds)
137+
138+
// Part 2: verify extraction with only the incrementally-collected job raw data
139+
// (jobs for workflows from pipelines #4-9 only).
140+
dataflowTester.ImportCsvIntoRawTable("./raw_tables/_raw_circleci_api_projects.csv", "_raw_circleci_api_projects")
141+
dataflowTester.FlushTabler(&models.CircleciProject{})
142+
dataflowTester.Subtask(tasks.ExtractProjectsMeta, taskData)
143+
144+
dataflowTester.ImportCsvIntoRawTable("./raw_tables/_raw_circleci_api_jobs_incremental.csv", "_raw_circleci_api_jobs")
145+
dataflowTester.FlushTabler(&models.CircleciJob{})
146+
dataflowTester.Subtask(tasks.ExtractJobsMeta, taskData)
147+
dataflowTester.VerifyTableWithOptions(
148+
models.CircleciJob{},
149+
e2ehelper.TableOptions{
150+
CSVRelPath: "./snapshot_tables/_tool_circleci_jobs_incremental.csv",
151+
IgnoreTypes: []interface{}{common.NoPKModel{}},
152+
},
153+
)
154+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
id,params,data,url,input,created_at
2+
20,"{""ConnectionId"":1,""ProjectSlug"":""github/coldgust/coldgust.github.io""}","{
3+
""dependencies"" : [ ],
4+
""job_number"" : 5,
5+
""id"" : ""ab8c3282-0e74-4a41-834e-152a71280bed"",
6+
""started_at"" : ""2023-03-25T17:52:20Z"",
7+
""created_at"" : ""2023-03-25T17:52:20Z"",
8+
""name"" : ""build"",
9+
""project_slug"" : ""gh/coldgust/coldgust.github.io"",
10+
""status"" : ""failed"",
11+
""type"" : ""build"",
12+
""stopped_at"" : ""2023-03-25T17:52:23Z""
13+
}",https://circleci.com/api/v2/workflow/6731159f-5275-4bfa-ba70-39d343d63814/job,"{""id"": ""6731159f-5275-4bfa-ba70-39d343d63814"", ""tag"": """", ""name"": """", ""status"": """", ""createdAt"": ""0001-01-01T00:00:00Z"", ""updatedAt"": ""0001-01-01T00:00:00Z"", ""created_at"": null, ""errored_by"": """", ""started_by"": """", ""stopped_at"": null, ""canceled_by"": """", ""pipeline_id"": ""23622ee4-e150-4920-9d66-81533fa765a4"", ""ConnectionId"": 0, ""_raw_data_id"": 0, ""duration_sec"": 0, ""project_slug"": """", ""_raw_data_table"": """", ""pipeline_number"": 0, ""_raw_data_params"": """", ""_raw_data_remark"": """"}",2023-03-28 15:39:58.775
14+
21,"{""ConnectionId"":1,""ProjectSlug"":""github/coldgust/coldgust.github.io""}","{
15+
""dependencies"" : [ ],
16+
""job_number"" : 7,
17+
""id"" : ""a00f80bc-f759-4900-97a5-2d121d80bde8"",
18+
""started_at"" : ""2023-03-25T17:56:27Z"",
19+
""created_at"" : ""2023-03-25T17:56:27Z"",
20+
""name"" : ""build"",
21+
""project_slug"" : ""gh/coldgust/coldgust.github.io"",
22+
""status"" : ""failed"",
23+
""type"" : ""build"",
24+
""stopped_at"" : ""2023-03-25T17:56:43Z""
25+
}",https://circleci.com/api/v2/workflow/7370985a-9de3-4a47-acbc-e6a1fe8e5812/job,"{""id"": ""7370985a-9de3-4a47-acbc-e6a1fe8e5812"", ""tag"": """", ""name"": """", ""status"": """", ""createdAt"": ""0001-01-01T00:00:00Z"", ""updatedAt"": ""0001-01-01T00:00:00Z"", ""created_at"": null, ""errored_by"": """", ""started_by"": """", ""stopped_at"": null, ""canceled_by"": """", ""pipeline_id"": ""866e967d-f826-4470-aed6-fc0c92e98703"", ""ConnectionId"": 0, ""_raw_data_id"": 0, ""duration_sec"": 0, ""project_slug"": """", ""_raw_data_table"": """", ""pipeline_number"": 0, ""_raw_data_params"": """", ""_raw_data_remark"": """"}",2023-03-28 15:39:58.953
26+
23,"{""ConnectionId"":1,""ProjectSlug"":""github/coldgust/coldgust.github.io""}","{
27+
""dependencies"" : [ ],
28+
""job_number"" : 9,
29+
""id"" : ""2ff3594e-9da1-4306-aefa-77b72a97971e"",
30+
""started_at"" : ""2023-03-25T18:13:25Z"",
31+
""created_at"" : ""2023-03-25T18:13:25Z"",
32+
""name"" : ""build"",
33+
""project_slug"" : ""gh/coldgust/coldgust.github.io"",
34+
""status"" : ""success"",
35+
""type"" : ""build"",
36+
""stopped_at"" : ""2023-03-25T18:13:38Z""
37+
}",https://circleci.com/api/v2/workflow/fd0bd4f5-264f-4e3c-a151-06153c018f78/job,"{""id"": ""fd0bd4f5-264f-4e3c-a151-06153c018f78"", ""tag"": """", ""name"": """", ""status"": """", ""createdAt"": ""0001-01-01T00:00:00Z"", ""updatedAt"": ""0001-01-01T00:00:00Z"", ""created_at"": null, ""errored_by"": """", ""started_by"": """", ""stopped_at"": null, ""canceled_by"": """", ""pipeline_id"": ""7fcc1623-edcc-4a76-ad20-cd81aa83519f"", ""ConnectionId"": 0, ""_raw_data_id"": 0, ""duration_sec"": 0, ""project_slug"": """", ""_raw_data_table"": """", ""pipeline_number"": 0, ""_raw_data_params"": """", ""_raw_data_remark"": """"}",2023-03-28 15:39:59.299
38+
24,"{""ConnectionId"":1,""ProjectSlug"":""github/coldgust/coldgust.github.io""}","{
39+
""dependencies"" : [ ],
40+
""job_number"" : 6,
41+
""id"" : ""76c1f2cc-27ea-47aa-8167-48d2633abdba"",
42+
""started_at"" : ""2023-03-25T17:54:11Z"",
43+
""created_at"" : ""2023-03-25T17:54:11Z"",
44+
""name"" : ""build"",
45+
""project_slug"" : ""gh/coldgust/coldgust.github.io"",
46+
""status"" : ""failed"",
47+
""type"" : ""build"",
48+
""stopped_at"" : ""2023-03-25T17:54:23Z""
49+
}",https://circleci.com/api/v2/workflow/b9ab7bbe-2f30-4c59-b4e2-eb2005bffb14/job,"{""id"": ""b9ab7bbe-2f30-4c59-b4e2-eb2005bffb14"", ""tag"": """", ""name"": """", ""status"": """", ""createdAt"": ""0001-01-01T00:00:00Z"", ""updatedAt"": ""0001-01-01T00:00:00Z"", ""created_at"": null, ""errored_by"": """", ""started_by"": """", ""stopped_at"": null, ""canceled_by"": """", ""pipeline_id"": ""70f3eb15-3b94-4f80-b65e-f23f4b74c33a"", ""ConnectionId"": 0, ""_raw_data_id"": 0, ""duration_sec"": 0, ""project_slug"": """", ""_raw_data_table"": """", ""pipeline_number"": 0, ""_raw_data_params"": """", ""_raw_data_remark"": """"}",2023-03-28 15:39:59.482
50+
25,"{""ConnectionId"":1,""ProjectSlug"":""github/coldgust/coldgust.github.io""}","{
51+
""dependencies"" : [ ],
52+
""job_number"" : 4,
53+
""id"" : ""a4af3dd5-a3ae-48e8-b634-e2d63aafbb5b"",
54+
""started_at"" : ""2023-03-25T17:50:22Z"",
55+
""created_at"" : ""2023-03-25T17:50:22Z"",
56+
""name"" : ""build"",
57+
""project_slug"" : ""gh/coldgust/coldgust.github.io"",
58+
""status"" : ""failed"",
59+
""type"" : ""build"",
60+
""stopped_at"" : ""2023-03-25T17:50:25Z""
61+
}",https://circleci.com/api/v2/workflow/c7df82a6-0d2b-4e19-a36a-3f3aa9fd3943/job,"{""id"": ""c7df82a6-0d2b-4e19-a36a-3f3aa9fd3943"", ""tag"": """", ""name"": """", ""status"": """", ""createdAt"": ""0001-01-01T00:00:00Z"", ""updatedAt"": ""0001-01-01T00:00:00Z"", ""created_at"": null, ""errored_by"": """", ""started_by"": """", ""stopped_at"": null, ""canceled_by"": """", ""pipeline_id"": ""2c45280f-7fb3-4025-b703-a547c4a94916"", ""ConnectionId"": 0, ""_raw_data_id"": 0, ""duration_sec"": 0, ""project_slug"": """", ""_raw_data_table"": """", ""pipeline_number"": 0, ""_raw_data_params"": """", ""_raw_data_remark"": """"}",2023-03-28 15:39:59.663
62+
27,"{""ConnectionId"":1,""ProjectSlug"":""github/coldgust/coldgust.github.io""}","{
63+
""dependencies"" : [ ],
64+
""job_number"" : 8,
65+
""id"" : ""004e3e27-17d7-4ccb-9b21-a7f55bcf2b3e"",
66+
""started_at"" : ""2023-03-25T18:06:15Z"",
67+
""created_at"" : ""2023-03-25T18:06:15Z"",
68+
""name"" : ""build"",
69+
""project_slug"" : ""gh/coldgust/coldgust.github.io"",
70+
""status"" : ""failed"",
71+
""type"" : ""build"",
72+
""stopped_at"" : ""2023-03-25T18:06:28Z""
73+
}",https://circleci.com/api/v2/workflow/fc76deef-bcdd-4856-8e96-a8e2d1c5a85f/job,"{""id"": ""fc76deef-bcdd-4856-8e96-a8e2d1c5a85f"", ""tag"": """", ""name"": """", ""status"": """", ""createdAt"": ""0001-01-01T00:00:00Z"", ""updatedAt"": ""0001-01-01T00:00:00Z"", ""created_at"": null, ""errored_by"": """", ""started_by"": """", ""stopped_at"": null, ""canceled_by"": """", ""pipeline_id"": ""afe0cabe-e7ee-4eb7-bf13-bb6170d139f0"", ""ConnectionId"": 0, ""_raw_data_id"": 0, ""duration_sec"": 0, ""project_slug"": """", ""_raw_data_table"": """", ""pipeline_number"": 0, ""_raw_data_params"": """", ""_raw_data_remark"": """"}",2023-03-28 15:40:00.022

0 commit comments

Comments
 (0)