Skip to content

Commit d98e784

Browse files
RazvanLiviuVarzarufauust
authored andcommitted
MDBF-1158: Implement MTR stdout log parsing
Related: MariaDB/mtr-log-collector#1 This patch can be merged without waiting for MariaDB/mtr-log-collector#1 . Clients will continue to use .xml files, ensuring backward compatibility. A separate patch will update the clients to use `stdout.log` files. Changes: - Update mtr_reporter.sh to handle log files - Introduce a dry-run option for local testing - Make the service name more generic: `MTR_LOG_COLLECTOR_BASE_URL` - Update `MTRReporter` to handle both XML and log formats; XML remains the default to avoid breaking existing clients
1 parent 7615a91 commit d98e784

8 files changed

Lines changed: 139 additions & 50 deletions

File tree

configuration/builders/sequences/debug.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from pathlib import PurePath
22

33
from configuration.builders.infra.runtime import BuildSequence, InContainer
4-
from configuration.builders.sequences.helpers import mtr_junit_reporter, save_mtr_logs
4+
from configuration.builders.sequences.helpers import mtr_reporter, save_mtr_logs
55
from configuration.steps.base import StepOptions
66
from configuration.steps.commands.compile import MAKE, CompileMakeCommand
77
from configuration.steps.commands.configure import ConfigureMariaDBCMake
@@ -170,7 +170,7 @@ def openssl_fips(
170170
)
171171

172172
sequence.add_step(
173-
mtr_junit_reporter(
173+
mtr_reporter(
174174
step_wrapping_fn=lambda step: InContainer(
175175
docker_environment=config, step=step
176176
),

configuration/builders/sequences/helpers.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ def add_test_suites_steps(
340340
)
341341

342342
steps.append(
343-
mtr_junit_reporter(
343+
mtr_reporter(
344344
step_wrapping_fn=lambda step: InContainer(
345345
docker_environment=config, step=step
346346
),
@@ -373,7 +373,7 @@ def save_mtr_logs(
373373
)
374374

375375

376-
def mtr_junit_reporter(
376+
def mtr_reporter(
377377
step_wrapping_fn=lambda step: step,
378378
):
379379
return step_wrapping_fn(

configuration/builders/sequences/mtr_extra_coverage.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from pathlib import PurePath
22

33
from configuration.builders.infra.runtime import BuildSequence, InContainer
4-
from configuration.builders.sequences.helpers import mtr_junit_reporter, save_mtr_logs
4+
from configuration.builders.sequences.helpers import mtr_reporter, save_mtr_logs
55
from configuration.steps.base import StepOptions
66
from configuration.steps.commands.compile import MAKE, CompileMakeCommand
77
from configuration.steps.commands.configure import ConfigureMariaDBCMake
@@ -120,7 +120,7 @@ def big_test(config, jobs):
120120
)
121121

122122
sequence.add_step(
123-
mtr_junit_reporter(
123+
mtr_reporter(
124124
step_wrapping_fn=lambda step: InContainer(
125125
docker_environment=config, step=step
126126
),

configuration/builders/sequences/sanitizers.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
get_mtr_normal_steps,
1010
get_mtr_s3_steps,
1111
get_mtr_spider_steps,
12-
mtr_junit_reporter,
12+
mtr_reporter,
1313
save_mtr_logs,
1414
)
1515
from configuration.steps.base import StepOptions
@@ -170,7 +170,7 @@ def asan_ubsan(
170170
docker_environment=config, step=step
171171
),
172172
),
173-
mtr_junit_reporter(
173+
mtr_reporter(
174174
step_wrapping_fn=lambda step: InContainer(
175175
docker_environment=config, step=step
176176
),
@@ -296,7 +296,7 @@ def msan(
296296
docker_environment=config, step=step
297297
),
298298
),
299-
mtr_junit_reporter(
299+
mtr_reporter(
300300
step_wrapping_fn=lambda step: InContainer(
301301
docker_environment=config, step=step
302302
),

configuration/steps/commands/mtr.py

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import os
2+
from enum import Enum
23
from pathlib import PurePath
34

45
from buildbot.plugins import util
@@ -112,23 +113,51 @@ def _save_logs(self) -> str:
112113
"""
113114

114115

116+
class ContentKind(str, Enum):
117+
"""Enumeration for the kind of content to report to the MTR log collector."""
118+
119+
XML = "xml"
120+
LOG = "log"
121+
122+
115123
class MTRReporter(BashScriptCommand):
116124
"""
117-
A command to transfer all the MTR JUnit test results to the mtr_junit_collector service.
125+
A command to report MTR test results to the MTR log collector.
118126
Attributes:
119-
directory (PurePath): The directory containing the MTR test results.
127+
workdir (PurePath): The working directory for the command.
128+
content_kind (ContentKind): The kind of content to report (XML or LOG).
129+
dry_run (bool): Whether to perform a dry run without actual upload.
130+
131+
XML files are searched in the workdir, without traversing subdirectories.
132+
133+
LOG files are searched in the path workdir/*/log/stdout.log
120134
"""
121135

122-
JUNIT_COLLECTOR_BASE_URL = os.environ.get("JUNIT_COLLECTOR_BASE_URL")
136+
MTR_LOG_COLLECTOR_BASE_URL = os.environ.get("MTR_LOG_COLLECTOR_BASE_URL")
123137

124-
def __init__(self, workdir: PurePath = PurePath(".")):
125-
base_url = self.JUNIT_COLLECTOR_BASE_URL
138+
def __init__(
139+
self,
140+
workdir: PurePath = PurePath("."),
141+
content_kind: ContentKind = ContentKind.XML,
142+
dry_run: bool = False,
143+
):
144+
base_url = self.MTR_LOG_COLLECTOR_BASE_URL
126145
branch = util.Interpolate("%(prop:branch)s")
127146
revision = util.Interpolate("%(prop:revision)s")
128147
platform = util.Interpolate("%(prop:buildername)s")
129148
bbnum = util.Interpolate("%(prop:buildnumber)s")
130149
dir = "."
131150

132-
args = [base_url, branch, revision, platform, bbnum, dir]
151+
args = [
152+
base_url,
153+
branch,
154+
revision,
155+
platform,
156+
bbnum,
157+
dir,
158+
content_kind.value,
159+
"1" if dry_run else "0",
160+
]
161+
133162
super().__init__(script_name="mtr_reporter.sh", args=args, workdir=workdir)
134163
self.name = "Save test results for CrossReference"

configuration/steps/commands/scripts/mtr_reporter.sh

Lines changed: 93 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@
33
set -euo pipefail
44

55
# Input variables
6-
BASE_URL="$1" # e.g., 100.64.101.1:9990
6+
BASE_URL="$1" # e.g., 100.64.101.1:9990
77
BRANCH="$2"
88
REVISION="$3"
99
PLATFORM="$4"
1010
BBNUM="$5"
11-
DIR="$6" # Directory containing .xml files
11+
DIR="$6" # Base directory containing either .xml files OR component/log/stdout.log
12+
CONTENT_KIND="$7" # "xml" or "log"
13+
DRY_RUN="${8:-0}" # "1" = print curl commands only, "0" = actually run (default)
1214

1315
err() {
1416
set +x
@@ -25,59 +27,117 @@ bb_log_info() {
2527
UPLOAD_URL="${BASE_URL}/upload-test-results/"
2628
HEALTH_URL="${BASE_URL}/health"
2729

28-
# Step 1: Health check before uploads
30+
# Validate mode inputs early
31+
case "$CONTENT_KIND" in
32+
xml|log) ;;
33+
*) err "Error: CONTENT_KIND must be 'xml' or 'log' (got: '$CONTENT_KIND')" ;;
34+
esac
35+
36+
case "$DRY_RUN" in
37+
0|1) ;;
38+
*) err "Error: DRY_RUN must be 0 or 1 (got: '$DRY_RUN')" ;;
39+
esac
40+
41+
# Step 1: Health check before uploads (skip if dry run)
2942
command -v curl >/dev/null || err "curl not found"
30-
bb_log_info "Checking service health at $HEALTH_URL..."
31-
if ! curl "$HEALTH_URL" \
32-
--max-time 5 \
33-
--retry 3 \
34-
--retry-max-time 0 \
35-
--retry-delay 5 \
36-
--retry-connrefused \
37-
--fail-with-body; then
38-
err "Service health check failed. Aborting uploads."
43+
44+
if [[ "$DRY_RUN" == "1" ]]; then
45+
bb_log_info "DRY RUN enabled: skipping health check and uploads will not be executed."
46+
else
47+
bb_log_info "Checking service health at $HEALTH_URL..."
48+
if ! curl "$HEALTH_URL" \
49+
--max-time 5 \
50+
--retry 3 \
51+
--retry-max-time 0 \
52+
--retry-delay 5 \
53+
--retry-connrefused \
54+
--fail-with-body; then
55+
err "Service health check failed. Aborting uploads."
56+
fi
57+
bb_log_info "Service is healthy. Proceeding with uploads."
3958
fi
40-
bb_log_info "Service is healthy. Proceeding with uploads."
4159

4260
# Step 2: Validate directory
4361
if [[ ! -d "$DIR" ]]; then
4462
err "Error: directory '$DIR' does not exist"
4563
fi
4664

47-
# Step 3: Find XML files
65+
# Step 3: Discover files based on content kind
4866
shopt -s nullglob
49-
XML_FILES=("$DIR"/*.xml)
67+
FILES=()
68+
if [[ "$CONTENT_KIND" == "xml" ]]; then
69+
FILES=("$DIR"/*.xml)
70+
else
71+
# stdout.log in: <DIR>/<component>/log/stdout.log
72+
FILES=("$DIR"/*/log/stdout.log)
73+
fi
5074
shopt -u nullglob
5175

52-
if (( ${#XML_FILES[@]} == 0 )); then
53-
err "Error: no .xml files found in directory '$DIR'"
76+
if (( ${#FILES[@]} == 0 )); then
77+
if [[ "$CONTENT_KIND" == "xml" ]]; then
78+
err "Error: no .xml files found in directory '$DIR'"
79+
else
80+
err "Error: no stdout.log files found under '$DIR' (expected: <component>/log/stdout.log)"
81+
fi
5482
fi
5583

84+
# Helper: print an argv array as a shell-escaped command (safe for copy/paste)
85+
print_cmd() {
86+
local -a argv=( "$@" )
87+
printf '%q ' "${argv[@]}"
88+
printf '\n'
89+
}
90+
5691
# Step 4: Upload files and track failures
5792
ANY_FAILED=0
5893

59-
for FILE in "${XML_FILES[@]}"; do
60-
# Extract filename without extension for 'typ'
61-
BASENAME="$(basename "$FILE" .xml)"
62-
bb_log_info "Uploading $FILE (typ=$BASENAME)..."
63-
64-
if ! curl --max-time 120 --connect-timeout 10 --fail-with-body \
65-
-X POST "$UPLOAD_URL" \
66-
-F "branch=${BRANCH}" \
67-
-F "revision=${REVISION}" \
68-
-F "platform=${PLATFORM}" \
69-
-F "bbnum=${BBNUM}" \
70-
-F "typ=${BASENAME}" \
71-
-F "file=@${FILE};type=application/xml"; then
72-
bb_log_info "Upload failed for $FILE"
73-
ANY_FAILED=1
94+
for FILE in "${FILES[@]}"; do
95+
BASENAME=""
96+
MIME_TYPE=""
97+
98+
if [[ "$CONTENT_KIND" == "xml" ]]; then
99+
BASENAME="$(basename "$FILE" .xml)"
100+
MIME_TYPE="application/xml"
101+
else
102+
COMPONENT_DIR="$(dirname "$(dirname "$FILE")")" # .../<component>
103+
BASENAME="$(basename "$COMPONENT_DIR")"
104+
MIME_TYPE="text/plain"
105+
fi
106+
107+
bb_log_info "Preparing upload for $FILE (typ=$BASENAME)..."
108+
109+
CURL_CMD=(
110+
curl
111+
--max-time 120
112+
--connect-timeout 10
113+
--fail-with-body
114+
-X POST "$UPLOAD_URL"
115+
-F "branch=${BRANCH}"
116+
-F "revision=${REVISION}"
117+
-F "platform=${PLATFORM}"
118+
-F "bbnum=${BBNUM}"
119+
-F "typ=${BASENAME}"
120+
-F "file=@${FILE};type=${MIME_TYPE}"
121+
)
122+
123+
if (( DRY_RUN == 1 )); then
124+
bb_log_info "DRY RUN: would execute:"
125+
print_cmd "${CURL_CMD[@]}"
126+
continue
127+
fi
128+
129+
if ! "${CURL_CMD[@]}"; then
130+
bb_log_info "Upload failed for $FILE"
131+
ANY_FAILED=1
74132
else
75133
bb_log_info "Upload succeeded for $FILE"
76134
fi
77135
done
78136

79137
# Step 5: Final result
80-
if ((ANY_FAILED != 0 )); then
138+
if (( DRY_RUN == 1 )); then
139+
bb_log_info "DRY RUN complete: no network calls were made."
140+
elif ((ANY_FAILED != 0 )); then
81141
err "One or more uploads failed."
82142
else
83143
bb_log_info "All uploads succeeded."

docker-compose/.env

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ TITLE='MariaDB CI'
22
TITLE_URL='https://github.com/MariaDB/server'
33
BUILDMASTER_URL='https://buildbot.mariadb.org/'
44
BUILDMASTER_WG_IP='100.64.100.1'
5-
JUNIT_COLLECTOR_BASE_URL='http://100.64.100.1:9990'
5+
MTR_LOG_COLLECTOR_BASE_URL='http://100.64.100.1:9990'
66
MQ_ROUTER_URL='ws://127.0.0.1:8080/ws'
77
MASTER_PACKAGES_DIR='/mnt/autofs/master_packages'
88
MASTER_CREDENTIALS_DIR='/srv/buildbot/master/master-credential-provider'

docker-compose/.env.dev

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ TITLE='MariaDB CI (DEV)'
22
TITLE_URL='https://github.com/MariaDB/server'
33
BUILDMASTER_URL='https://buildbot.dev.mariadb.org/'
44
BUILDMASTER_WG_IP='100.64.101.1'
5-
JUNIT_COLLECTOR_BASE_URL='http://100.64.101.1:9990'
5+
MTR_LOG_COLLECTOR_BASE_URL='http://100.64.101.1:9990'
66
MQ_ROUTER_URL='ws://127.0.0.1:8080/ws'
77
MASTER_PACKAGES_DIR='/mnt/autofs/master_dev_packages'
88
MASTER_CREDENTIALS_DIR='/srv/buildbot/master/master-credential-provider'

0 commit comments

Comments
 (0)