Skip to content

Commit 9969044

Browse files
authored
New package static quality gates (#33878)
1 parent b62cc23 commit 9969044

21 files changed

+298
-102
lines changed

.gitlab/functional_test/static_quality_gate.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,16 @@ static_quality_gates:
99
needs:
1010
- job: agent_deb-x64-a7
1111
artifacts: true
12+
- job: agent_deb-arm64-a7
13+
artifacts: true
14+
- job: agent_rpm-x64-a7
15+
artifacts: true
16+
- job: agent_rpm-arm64-a7
17+
artifacts: true
18+
- job: agent_suse-x64-a7
19+
artifacts: true
20+
- job: agent_suse-arm64-a7
21+
artifacts: true
1222
- job: docker_build_agent7
1323
artifacts: true
1424
- job: docker_build_agent7_arm64
@@ -21,6 +31,28 @@ static_quality_gates:
2131
artifacts: true
2232
- job: docker_build_cluster_agent_arm64
2333
artifacts: true
34+
- job: docker_build_dogstatsd_amd64
35+
artifacts: true
36+
- job: docker_build_dogstatsd_arm64
37+
artifacts: true
38+
- job: dogstatsd_deb-x64
39+
artifacts: true
40+
- job: dogstatsd_deb-arm64
41+
artifacts: true
42+
- job: dogstatsd_rpm-x64
43+
artifacts: true
44+
- job: dogstatsd_suse-x64
45+
artifacts: true
46+
- job: iot_agent_deb-x64
47+
artifacts: true
48+
- job: iot_agent_deb-arm64
49+
artifacts: true
50+
- job: iot_agent_rpm-x64
51+
artifacts: true
52+
- job: iot_agent_rpm-arm64
53+
artifacts: true
54+
- job: iot_agent_suse-x64
55+
artifacts: true
2456
# Static Quality Gates aren't enforced until Q1
2557
allow_failure: true
2658
script:

tasks/quality_gates.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ def display_pr_comment(
3939
:return:
4040
"""
4141
title = f"Static quality checks {SUCCESS_CHAR if final_state else FAIL_CHAR}"
42-
body_info = body_pattern.format("Info")
42+
body_info = "<details>\n<summary>Successful checks</summary>\n\n" + body_pattern.format("Info")
4343
body_error = body_pattern.format("Error")
4444
body_error_footer = body_error_footer_pattern
4545

@@ -64,6 +64,7 @@ def getMetric(metric_name, gate_name=gate['name']):
6464
with_error = True
6565

6666
body_error_footer += "\n</details>\n"
67+
body_info += "\n</details>\n"
6768
body = f"Please find below the results from static quality gates\n{body_error+body_error_footer if with_error else ''}\n\n{body_info if with_info else ''}"
6869

6970
pr_commenter(ctx, title=title, body=body)

tasks/static_quality_gates/lib/gates_lib.py

Lines changed: 31 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,14 @@ def find_package_path(flavor, package_os, arch):
7979

8080

8181
class GateMetricHandler:
82+
# All metric_name -> metric_key
83+
METRICS_DICT = {
84+
"datadog.agent.static_quality_gate.on_wire_size": "current_on_wire_size",
85+
"datadog.agent.static_quality_gate.on_disk_size": "current_on_disk_size",
86+
"datadog.agent.static_quality_gate.max_allowed_on_wire_size": "max_on_wire_size",
87+
"datadog.agent.static_quality_gate.max_allowed_on_disk_size": "max_on_disk_size",
88+
}
89+
8290
def __init__(self, git_ref, bucket_branch):
8391
self.metrics = {}
8492
self.metadata = {}
@@ -101,6 +109,18 @@ def register_gate_tags(self, gate, **kwargs):
101109
for key in kwargs:
102110
self.metadata[gate][key] = kwargs[key]
103111

112+
def _add_gauge(self, timestamp, common_tags, gate, metric_name, metric_key):
113+
if self.metrics[gate].get(metric_key):
114+
return create_gauge(
115+
metric_name,
116+
timestamp,
117+
self.metrics[gate][metric_key],
118+
tags=common_tags,
119+
metric_origin=get_metric_origin(ORIGIN_PRODUCT, ORIGIN_CATEGORY, ORIGIN_SERVICE),
120+
unit="byte",
121+
)
122+
return None
123+
104124
def _generate_series(self):
105125
if not self.git_ref or not self.bucket_branch:
106126
return None
@@ -120,46 +140,17 @@ def _generate_series(self):
120140
for tag in self.metadata[gate]:
121141
common_tags.append(f"{tag}:{self.metadata[gate][tag]}")
122142

123-
series.append(
124-
create_gauge(
125-
"datadog.agent.static_quality_gate.on_wire_size",
126-
timestamp,
127-
self.metrics[gate]["current_on_wire_size"],
128-
tags=common_tags,
129-
metric_origin=get_metric_origin(ORIGIN_PRODUCT, ORIGIN_CATEGORY, ORIGIN_SERVICE),
130-
unit="byte",
131-
),
132-
)
133-
series.append(
134-
create_gauge(
135-
"datadog.agent.static_quality_gate.on_disk_size",
136-
timestamp,
137-
self.metrics[gate]["current_on_disk_size"],
138-
tags=common_tags,
139-
metric_origin=get_metric_origin(ORIGIN_PRODUCT, ORIGIN_CATEGORY, ORIGIN_SERVICE),
140-
unit="byte",
141-
),
142-
)
143-
series.append(
144-
create_gauge(
145-
"datadog.agent.static_quality_gate.max_allowed_on_wire_size",
146-
timestamp,
147-
self.metrics[gate]["max_on_wire_size"],
148-
tags=common_tags,
149-
metric_origin=get_metric_origin(ORIGIN_PRODUCT, ORIGIN_CATEGORY, ORIGIN_SERVICE),
150-
unit="byte",
151-
),
152-
)
153-
series.append(
154-
create_gauge(
155-
"datadog.agent.static_quality_gate.max_allowed_on_disk_size",
156-
timestamp,
157-
self.metrics[gate]["max_on_disk_size"],
158-
tags=common_tags,
159-
metric_origin=get_metric_origin(ORIGIN_PRODUCT, ORIGIN_CATEGORY, ORIGIN_SERVICE),
160-
unit="byte",
161-
),
162-
)
143+
for metric_name, metric_key in self.METRICS_DICT.items():
144+
gauge = self._add_gauge(timestamp, common_tags, gate, metric_name, metric_key)
145+
if gauge:
146+
series.append(gauge)
147+
else:
148+
print(
149+
color_message(
150+
f"[WARN] gate {gate} doesn't have the {metric_name} metric registered ! skipping metric...",
151+
"orange",
152+
)
153+
)
163154
return series
164155

165156
def send_metrics_to_datadog(self):
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import tempfile
2+
3+
from tasks.libs.common.color import color_message
4+
from tasks.libs.package.size import directory_size, extract_package, file_size
5+
from tasks.static_quality_gates.lib.gates_lib import argument_extractor, find_package_path, read_byte_input
6+
7+
8+
def calculate_package_size(ctx, package_os, package_path, gate_name, metric_handler):
9+
with tempfile.TemporaryDirectory() as extract_dir:
10+
extract_package(ctx=ctx, package_os=package_os, package_path=package_path, extract_dir=extract_dir)
11+
package_on_wire_size = file_size(path=package_path)
12+
package_on_disk_size = directory_size(ctx, path=extract_dir)
13+
14+
metric_handler.register_metric(gate_name, "current_on_wire_size", package_on_wire_size)
15+
metric_handler.register_metric(gate_name, "current_on_disk_size", package_on_disk_size)
16+
return package_on_wire_size, package_on_disk_size
17+
18+
19+
def check_package_size(package_on_wire_size, package_on_disk_size, max_on_wire_size, max_on_disk_size):
20+
error_message = ""
21+
if package_on_wire_size > max_on_wire_size:
22+
err_msg = f"Package size on wire (compressed package size) {package_on_wire_size} is higher than the maximum allowed {max_on_wire_size} by the gate !\n"
23+
print(color_message(err_msg, "red"))
24+
error_message += err_msg
25+
else:
26+
print(
27+
color_message(
28+
f"package_on_wire_size <= max_on_wire_size, ({package_on_wire_size}) <= ({max_on_wire_size})",
29+
"green",
30+
)
31+
)
32+
if package_on_disk_size > max_on_disk_size:
33+
err_msg = f"Package size on disk (uncompressed package size) {package_on_disk_size} is higher than the maximum allowed {max_on_disk_size} by the gate !\n"
34+
print(color_message(err_msg, "red"))
35+
error_message += err_msg
36+
else:
37+
print(
38+
color_message(
39+
f"package_on_disk_size <= max_on_disk_size, ({package_on_disk_size}) <= ({max_on_disk_size})",
40+
"green",
41+
)
42+
)
43+
if error_message != "":
44+
raise AssertionError(error_message)
45+
46+
47+
def generic_package_agent_quality_gate(gate_name, arch, os, flavor, **kwargs):
48+
arguments = argument_extractor(
49+
kwargs, max_on_wire_size=read_byte_input, max_on_disk_size=read_byte_input, ctx=None, metricHandler=None
50+
)
51+
ctx = arguments.ctx
52+
metric_handler = arguments.metricHandler
53+
max_on_wire_size = arguments.max_on_wire_size
54+
max_on_disk_size = arguments.max_on_disk_size
55+
56+
metric_handler.register_gate_tags(gate_name, gate_name=gate_name, arch=arch, os=os)
57+
58+
metric_handler.register_metric(gate_name, "max_on_wire_size", max_on_wire_size)
59+
metric_handler.register_metric(gate_name, "max_on_disk_size", max_on_disk_size)
60+
package_arm = arch
61+
if os == "centos" or os == "suse":
62+
if arch == "arm64":
63+
package_arm = "aarch64"
64+
elif arch == "amd64":
65+
package_arm = "x86_64"
66+
67+
package_path = find_package_path(flavor, os, package_arm)
68+
69+
package_on_wire_size, package_on_disk_size = calculate_package_size(
70+
ctx, os, package_path, gate_name, metric_handler
71+
)
72+
check_package_size(package_on_wire_size, package_on_disk_size, max_on_wire_size, max_on_disk_size)
Lines changed: 3 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,7 @@
1-
import tempfile
2-
3-
from tasks.libs.common.color import color_message
4-
from tasks.libs.package.size import directory_size, extract_package, file_size
5-
from tasks.static_quality_gates.lib.gates_lib import argument_extractor, find_package_path, read_byte_input
1+
from tasks.static_quality_gates.lib.package_agent_lib import generic_package_agent_quality_gate
62

73

84
def entrypoint(**kwargs):
9-
arguments = argument_extractor(
10-
kwargs, max_on_wire_size=read_byte_input, max_on_disk_size=read_byte_input, ctx=None, metricHandler=None
11-
)
12-
ctx = arguments.ctx
13-
metric_handler = arguments.metricHandler
14-
max_on_wire_size = arguments.max_on_wire_size
15-
max_on_disk_size = arguments.max_on_disk_size
16-
17-
metric_handler.register_gate_tags(
18-
"static_quality_gate_agent_deb_amd64", gate_name="static_quality_gate_agent_deb_amd64", arch="x64", os="debian"
5+
generic_package_agent_quality_gate(
6+
"static_quality_gate_agent_deb_amd64", "amd64", "debian", "datadog-agent", **kwargs
197
)
20-
21-
metric_handler.register_metric("static_quality_gate_agent_deb_amd64", "max_on_wire_size", max_on_wire_size)
22-
metric_handler.register_metric("static_quality_gate_agent_deb_amd64", "max_on_disk_size", max_on_disk_size)
23-
24-
package_os = "debian"
25-
package_path = find_package_path("datadog-agent", package_os, "amd64")
26-
27-
with tempfile.TemporaryDirectory() as extract_dir:
28-
extract_package(ctx=ctx, package_os=package_os, package_path=package_path, extract_dir=extract_dir)
29-
package_on_wire_size = file_size(path=package_path)
30-
package_on_disk_size = directory_size(ctx, path=extract_dir)
31-
32-
metric_handler.register_metric(
33-
"static_quality_gate_agent_deb_amd64", "current_on_wire_size", package_on_wire_size
34-
)
35-
metric_handler.register_metric(
36-
"static_quality_gate_agent_deb_amd64", "current_on_disk_size", package_on_disk_size
37-
)
38-
39-
error_message = ""
40-
if package_on_wire_size > max_on_wire_size:
41-
err_msg = f"Package size on wire (compressed package size) {package_on_wire_size} is higher than the maximum allowed {max_on_wire_size} by the gate !\n"
42-
print(color_message(err_msg, "red"))
43-
error_message += err_msg
44-
else:
45-
print(
46-
color_message(
47-
f"package_on_wire_size <= max_on_wire_size, ({package_on_wire_size}) <= ({max_on_wire_size})",
48-
"green",
49-
)
50-
)
51-
if package_on_disk_size > max_on_disk_size:
52-
err_msg = f"Package size on disk (uncompressed package size) {package_on_disk_size} is higher than the maximum allowed {max_on_disk_size} by the gate !\n"
53-
print(color_message(err_msg, "red"))
54-
error_message += err_msg
55-
else:
56-
print(
57-
color_message(
58-
f"package_on_disk_size <= max_on_disk_size, ({package_on_disk_size}) <= ({max_on_disk_size})",
59-
"green",
60-
)
61-
)
62-
if error_message != "":
63-
raise AssertionError(error_message)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from tasks.static_quality_gates.lib.package_agent_lib import generic_package_agent_quality_gate
2+
3+
4+
def entrypoint(**kwargs):
5+
generic_package_agent_quality_gate(
6+
"static_quality_gate_agent_deb_arm64", "arm64", "debian", "datadog-agent", **kwargs
7+
)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from tasks.static_quality_gates.lib.package_agent_lib import generic_package_agent_quality_gate
2+
3+
4+
def entrypoint(**kwargs):
5+
generic_package_agent_quality_gate(
6+
"static_quality_gate_agent_rpm_amd64", "amd64", "centos", "datadog-agent", **kwargs
7+
)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from tasks.static_quality_gates.lib.package_agent_lib import generic_package_agent_quality_gate
2+
3+
4+
def entrypoint(**kwargs):
5+
generic_package_agent_quality_gate(
6+
"static_quality_gate_agent_rpm_arm64", "arm64", "centos", "datadog-agent", **kwargs
7+
)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from tasks.static_quality_gates.lib.package_agent_lib import generic_package_agent_quality_gate
2+
3+
4+
def entrypoint(**kwargs):
5+
generic_package_agent_quality_gate(
6+
"static_quality_gate_agent_suse_amd64", "amd64", "suse", "datadog-agent", **kwargs
7+
)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from tasks.static_quality_gates.lib.package_agent_lib import generic_package_agent_quality_gate
2+
3+
4+
def entrypoint(**kwargs):
5+
generic_package_agent_quality_gate(
6+
"static_quality_gate_agent_suse_arm64", "arm64", "suse", "datadog-agent", **kwargs
7+
)

0 commit comments

Comments
 (0)