From 1c65afdd283a5c513add113979f313d260ad4b91 Mon Sep 17 00:00:00 2001 From: Roman Kennke Date: Mon, 9 Nov 2026 19:21:28 +0000 Subject: [PATCH 1/3] Trigger the speedlab memory gate from branch pipelines A manual memory-gate job triggers speedlab's memory gate with this branch's published snapshot against main's. memory-gate:resolve pins the candidate to the timestamped build deploy-artifact published, so a later push cannot change what is measured, and passes it on as a dotenv variable. The trigger job inherits no global variables, so only its own reach speedlab. Speedlab posts the warn-only verdict on the PR. Neither job runs on main, tags or release branches. Co-Authored-By: Claude Opus 5.5 --- .gitlab-ci.yml | 2 + .gitlab/memory-gate/.gitlab-ci.yml | 51 +++++++++++++++ .gitlab/memory-gate/resolve-candidate.sh | 55 ++++++++++++++++ .../tests/resolve_candidate_test.sh | 62 +++++++++++++++++++ doc/README.md | 2 +- doc/building/TestingGuide.md | 15 +++++ 6 files changed, 186 insertions(+), 1 deletion(-) create mode 100644 .gitlab/memory-gate/.gitlab-ci.yml create mode 100755 .gitlab/memory-gate/resolve-candidate.sh create mode 100644 .gitlab/memory-gate/tests/resolve_candidate_test.sh diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 17a27d79d9..835f7f4041 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -146,6 +146,7 @@ shell-unit-tests: - bash .gitlab/scripts/tests/test_check_stack_top.sh - bash .gitlab/jdk-integration/tests/select_test_jdk_test.sh - bash .gitlab/dd-trace-integration/tests/post_pr_comment_test.sh + - bash .gitlab/memory-gate/tests/resolve_candidate_test.sh # Shared version detection used by benchmarks and reliability pipelines get-versions: @@ -257,3 +258,4 @@ include: - local: .gitlab/dd-trace-integration/.gitlab-ci.yml - local: .gitlab/sanitizer-tests/.gitlab-ci.yml - local: .gitlab/fuzzing/.gitlab-ci.yml + - local: .gitlab/memory-gate/.gitlab-ci.yml diff --git a/.gitlab/memory-gate/.gitlab-ci.yml b/.gitlab/memory-gate/.gitlab-ci.yml new file mode 100644 index 0000000000..f4e532967a --- /dev/null +++ b/.gitlab/memory-gate/.gitlab-ci.yml @@ -0,0 +1,51 @@ +# Memory gate: speedlab (DataDog/apm-reliability/speedlab, docs/memory-gate.md) +# compares spring-petclinic's memory with this branch's java-profiler build against +# main's, and posts a warn-only verdict on the PR. Manual: play `memory-gate`. + +.memory-gate-rules: + rules: + - !reference [.skip-on-release, rules] + - if: '$CI_COMMIT_TAG || $CI_COMMIT_BRANCH == "main"' + when: never # main against itself measures nothing + +# Pins the snapshot deploy-artifact published, for the trigger job's variables. +memory-gate:resolve: + stage: benchmarks + needs: + - job: deploy-artifact + artifacts: true + image: ${PREPARE_IMAGE} + tags: ["arch:amd64"] + rules: + - !reference [.memory-gate-rules, rules] + - when: on_success + script: + - bash .gitlab/memory-gate/resolve-candidate.sh version.txt memory-gate.env + artifacts: + reports: + dotenv: memory-gate.env + +memory-gate: + stage: benchmarks + needs: + - job: memory-gate:resolve + artifacts: true + rules: + - !reference [.memory-gate-rules, rules] + - when: manual + allow_failure: true + # Only the variables below reach speedlab: its jobs read ours, and upstream + # variables would override their own settings. + inherit: + variables: false + variables: + SPEEDLAB_TRIGGER: java-profiler-memory-gate + PROFILER_CANDIDATE: $MEMORY_GATE_CANDIDATE + PROFILER_BASELINE: branch:main + UPSTREAM_PROJECT_NAME: java-profiler + UPSTREAM_BRANCH: $CI_COMMIT_REF_NAME + UPSTREAM_COMMIT_SHA: $CI_COMMIT_SHA + trigger: + project: DataDog/apm-reliability/speedlab + # speedlab's trigger rules are on this branch until DataDog/speedlab#109 merges. + branch: rkennke/memory-gate-trigger diff --git a/.gitlab/memory-gate/resolve-candidate.sh b/.gitlab/memory-gate/resolve-candidate.sh new file mode 100755 index 0000000000..48c69ffbef --- /dev/null +++ b/.gitlab/memory-gate/resolve-candidate.sh @@ -0,0 +1,55 @@ +#!/usr/bin/env bash +# Copyright 2026, Datadog, Inc. +# +# Writes the memory gate's candidate, this pipeline's published snapshot build +# pinned by its timestamp, as a dotenv file for the speedlab trigger job: +# MEMORY_GATE_CANDIDATE=snapshot:1.54.0-my_branch-20261109.101500-3 +# A branch selector would be resolved again in speedlab and could pick a newer +# push; the timestamped build cannot change. +# +# Usage: resolve-candidate.sh [maven-metadata.xml] +# version.txt is deploy-artifact's ("com.datadoghq:ddprof:"). The +# metadata file defaults to the snapshot repository's for that version. +set -euo pipefail + +# The main jar's timestamped build in a snapshot's maven-metadata.xml (stdin): +# the last with no classifier and extension jar. +latest_jar_build() { + awk ' + // { classifier=""; extension=""; value="" } + // { classifier=$0; gsub(/.*|<\/classifier>.*/, "", classifier) } + // { extension=$0; gsub(/.*|<\/extension>.*/, "", extension) } + // { value=$0; gsub(/.*|<\/value>.*/, "", value) } + /<\/snapshotVersion>/ { if (classifier == "" && extension == "jar") last=value } + END { print last } + ' +} + +main() { + local version_file=$1 out=$2 metadata=${3:-} + local version + version=$(sed -n 's/^com\.datadoghq:ddprof://p' "$version_file") + if [[ "$version" != *-SNAPSHOT ]]; then + echo "ERROR: '${version}' from ${version_file} is not a snapshot version" >&2 + return 1 + fi + local build + if [ -n "$metadata" ]; then + build=$(latest_jar_build < "$metadata") + else + build=$(curl -fsSL --connect-timeout 10 --max-time 30 \ + "https://central.sonatype.com/repository/maven-snapshots/com/datadoghq/ddprof/${version}/maven-metadata.xml" \ + | latest_jar_build) + fi + # The build is the version with -SNAPSHOT replaced by .