From 61a7f688ebc0f4fe32503d6d3904a1ffd0cbe514 Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Tue, 4 Aug 2026 12:45:48 +0200 Subject: [PATCH 01/10] fix: skip jobs needing build/deploy-artifact on release/* branches build-artifact and deploy-artifact already skip on release/* branches, but prepare-patched-agent, integration-test-*, report-dd-trace-results, post-pr-comment, benchmarks-trigger, and notify-slack-on-* still needed them unconditionally, breaking pipeline creation with a "needs job does not exist" error. Co-Authored-By: Claude Sonnet 5 --- .gitlab/benchmarks/.gitlab-ci.yml | 2 ++ .gitlab/build-deploy/.gitlab-ci.yml | 10 ++++++++-- .gitlab/dd-trace-integration/.gitlab-ci.yml | 8 ++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/.gitlab/benchmarks/.gitlab-ci.yml b/.gitlab/benchmarks/.gitlab-ci.yml index b6f7f1cef5..3d68ac13f2 100644 --- a/.gitlab/benchmarks/.gitlab-ci.yml +++ b/.gitlab/benchmarks/.gitlab-ci.yml @@ -17,6 +17,8 @@ benchmarks-trigger: rules: - if: '$CANCELLED == "true"' when: never + - if: '$CI_COMMIT_BRANCH =~ /^release\//' + when: never - if: '$JDK_VERSION != null || $DEBUG_LEVEL != null || $HASH != null || $DOWNSTREAM != null' when: never - if: '$CI_PIPELINE_SOURCE == "schedule"' diff --git a/.gitlab/build-deploy/.gitlab-ci.yml b/.gitlab/build-deploy/.gitlab-ci.yml index 1d96d52390..e576e53d91 100644 --- a/.gitlab/build-deploy/.gitlab-ci.yml +++ b/.gitlab/build-deploy/.gitlab-ci.yml @@ -345,7 +345,10 @@ notify-slack-on-success: artifacts: true - job: deploy-artifact artifacts: false - when: on_success + rules: + - if: '$CI_COMMIT_BRANCH =~ /^release\//' + when: never + - when: on_success image: registry.ddbuild.io/slack-notifier:v91289620-4ec922a-latest@sha256:06b24f392ccc383d371c72001520a254edef523bc0bfdc445f487106107b4202 tags: ["arch:amd64"] script: @@ -359,7 +362,10 @@ notify-slack-on-failure: artifacts: true - job: deploy-artifact artifacts: true - when: on_failure + rules: + - if: '$CI_COMMIT_BRANCH =~ /^release\//' + when: never + - when: on_failure image: registry.ddbuild.io/slack-notifier:v91289620-4ec922a-latest@sha256:06b24f392ccc383d371c72001520a254edef523bc0bfdc445f487106107b4202 tags: ["arch:amd64"] script: diff --git a/.gitlab/dd-trace-integration/.gitlab-ci.yml b/.gitlab/dd-trace-integration/.gitlab-ci.yml index 22aa991b88..5ddb457735 100644 --- a/.gitlab/dd-trace-integration/.gitlab-ci.yml +++ b/.gitlab/dd-trace-integration/.gitlab-ci.yml @@ -17,6 +17,8 @@ prepare-patched-agent: - job: build-artifact artifacts: true rules: + - if: '$CI_COMMIT_BRANCH =~ /^release\//' + when: never - if: '$JDK_VERSION != null || $DEBUG_LEVEL != null || $HASH != null || $DOWNSTREAM != null' when: never - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' @@ -87,6 +89,8 @@ prepare-patched-agent: - job: prepare-patched-agent artifacts: true rules: + - if: '$CI_COMMIT_BRANCH =~ /^release\//' + when: never - if: '$JDK_VERSION != null || $DEBUG_LEVEL != null || $HASH != null || $DOWNSTREAM != null' when: never - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' @@ -268,6 +272,8 @@ report-dd-trace-results: - job: integration-test-arm64-musl artifacts: true rules: + - if: '$CI_COMMIT_BRANCH =~ /^release\//' + when: never - if: '$JDK_VERSION != null || $DEBUG_LEVEL != null || $HASH != null || $DOWNSTREAM != null' when: never - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' @@ -296,6 +302,8 @@ post-pr-comment: - job: integration-test-arm64-musl artifacts: true rules: + - if: '$CI_COMMIT_BRANCH =~ /^release\//' + when: never - if: '$JDK_VERSION != null || $DEBUG_LEVEL != null || $HASH != null || $DOWNSTREAM != null' when: never - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' From 351909f904480e9087a7a451925f9eb522d24357 Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Tue, 4 Aug 2026 13:38:11 +0200 Subject: [PATCH 02/10] fix: wait for snapshot artifact to propagate on Sonatype before returning deploy-artifact was reporting success before the published snapshot jar was fetchable from central.sonatype.com, causing benchmarks-trigger's downstream download to 404 moments later. Co-Authored-By: Claude Sonnet 5 --- .gitlab/scripts/deploy.sh | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/.gitlab/scripts/deploy.sh b/.gitlab/scripts/deploy.sh index c0e74f676d..cd215bccc5 100755 --- a/.gitlab/scripts/deploy.sh +++ b/.gitlab/scripts/deploy.sh @@ -48,4 +48,24 @@ if [ "$MODE" = "publish" ] || [ "$MODE" = "all" ]; then exit 1 fi ./gradlew -Pskip-native -Pskip-tests -Pddprof_version="${LIB_VERSION}" -PbuildInfo.build.number=$CI_JOB_ID -Pwith-libs="$(pwd)/libs" publishToSonatype closeAndReleaseSonatypeStagingRepository --exclude-task compileFuzzer --max-workers=1 --no-build-cache --stacktrace --info --no-watch-fs --no-daemon + + # Snapshot artifacts publish straight to the Central Portal snapshot repo (no + # staging/close/release step), but the repo can take a while to make a freshly + # published artifact fetchable. benchmarks-trigger downloads it immediately + # after this job succeeds, so poll until it's actually there before returning. + if [[ "${LIB_VERSION}" == *-SNAPSHOT ]]; then + JAR_URL="https://central.sonatype.com/repository/maven-snapshots/com/datadoghq/ddprof/${LIB_VERSION}/ddprof-${LIB_VERSION}-debug.jar" + echo "=== Waiting for snapshot artifact to propagate: ${JAR_URL} ===" + for attempt in $(seq 1 20); do + if curl -sf -o /dev/null "${JAR_URL}"; then + echo "Snapshot artifact available after ${attempt} attempt(s)" + break + fi + if [ "${attempt}" -eq 20 ]; then + echo "ERROR: snapshot artifact still not available after ${attempt} attempts" + exit 1 + fi + sleep 15 + done + fi fi From 9bea134846d7df37479ed04861342daeb2781966 Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Tue, 4 Aug 2026 14:18:54 +0200 Subject: [PATCH 03/10] Revert "fix: wait for snapshot artifact to propagate on Sonatype before returning" This reverts commit 351909f904480e9087a7a451925f9eb522d24357. --- .gitlab/scripts/deploy.sh | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/.gitlab/scripts/deploy.sh b/.gitlab/scripts/deploy.sh index cd215bccc5..c0e74f676d 100755 --- a/.gitlab/scripts/deploy.sh +++ b/.gitlab/scripts/deploy.sh @@ -48,24 +48,4 @@ if [ "$MODE" = "publish" ] || [ "$MODE" = "all" ]; then exit 1 fi ./gradlew -Pskip-native -Pskip-tests -Pddprof_version="${LIB_VERSION}" -PbuildInfo.build.number=$CI_JOB_ID -Pwith-libs="$(pwd)/libs" publishToSonatype closeAndReleaseSonatypeStagingRepository --exclude-task compileFuzzer --max-workers=1 --no-build-cache --stacktrace --info --no-watch-fs --no-daemon - - # Snapshot artifacts publish straight to the Central Portal snapshot repo (no - # staging/close/release step), but the repo can take a while to make a freshly - # published artifact fetchable. benchmarks-trigger downloads it immediately - # after this job succeeds, so poll until it's actually there before returning. - if [[ "${LIB_VERSION}" == *-SNAPSHOT ]]; then - JAR_URL="https://central.sonatype.com/repository/maven-snapshots/com/datadoghq/ddprof/${LIB_VERSION}/ddprof-${LIB_VERSION}-debug.jar" - echo "=== Waiting for snapshot artifact to propagate: ${JAR_URL} ===" - for attempt in $(seq 1 20); do - if curl -sf -o /dev/null "${JAR_URL}"; then - echo "Snapshot artifact available after ${attempt} attempt(s)" - break - fi - if [ "${attempt}" -eq 20 ]; then - echo "ERROR: snapshot artifact still not available after ${attempt} attempts" - exit 1 - fi - sleep 15 - done - fi fi From ff83df0bbe6d64198e420c74b122c81f59bb0615 Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Tue, 4 Aug 2026 14:25:03 +0200 Subject: [PATCH 04/10] fix: also publish snapshot jars under literal -SNAPSHOT filename Gradle's maven-publish always timestamps snapshot uploads, but benchmarking-platform's downloader fetches by the literal -SNAPSHOT filename instead of resolving maven-metadata.xml, so PR-branch benchmarks 404 on every run. Upload plain copies under the literal name it expects, alongside the canonical Gradle-managed artifact. Co-Authored-By: Claude Sonnet 5 --- .gitlab/scripts/deploy.sh | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.gitlab/scripts/deploy.sh b/.gitlab/scripts/deploy.sh index c0e74f676d..d78d763a95 100755 --- a/.gitlab/scripts/deploy.sh +++ b/.gitlab/scripts/deploy.sh @@ -48,4 +48,20 @@ if [ "$MODE" = "publish" ] || [ "$MODE" = "all" ]; then exit 1 fi ./gradlew -Pskip-native -Pskip-tests -Pddprof_version="${LIB_VERSION}" -PbuildInfo.build.number=$CI_JOB_ID -Pwith-libs="$(pwd)/libs" publishToSonatype closeAndReleaseSonatypeStagingRepository --exclude-task compileFuzzer --max-workers=1 --no-build-cache --stacktrace --info --no-watch-fs --no-daemon + + # Gradle's maven-publish always uploads snapshots under a unique timestamped + # filename (e.g. ddprof-1.2.3-branch-20260804.115820-1-debug.jar); there's no + # supported way to opt out of that. Some downstream consumers (e.g. the + # benchmarking-platform's downloader) fetch snapshots by the literal + # "-SNAPSHOT" filename instead of resolving maven-metadata.xml, so also + # publish plain copies of the locally-built jars under that literal name. + if [[ "${LIB_VERSION}" == *-SNAPSHOT ]]; then + echo "=== Publishing literal-named snapshot copies for non-metadata-aware consumers ===" + BASE_URL="https://central.sonatype.com/repository/maven-snapshots/com/datadoghq/ddprof/${LIB_VERSION}" + for jar in ddprof-lib/build/libs/ddprof-"${LIB_VERSION}"*.jar; do + [ -f "$jar" ] || continue + echo "Uploading $(basename "$jar")" + curl -sf -u "${SONATYPE_USERNAME}:${SONATYPE_PASSWORD}" --upload-file "$jar" "${BASE_URL}/$(basename "$jar")" + done + fi fi From 6a5265c19772526d77475cba61cd380677e53bff Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Tue, 4 Aug 2026 14:44:25 +0200 Subject: [PATCH 05/10] Revert "fix: also publish snapshot jars under literal -SNAPSHOT filename" This reverts commit ff83df0bbe6d64198e420c74b122c81f59bb0615. --- .gitlab/scripts/deploy.sh | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/.gitlab/scripts/deploy.sh b/.gitlab/scripts/deploy.sh index d78d763a95..c0e74f676d 100755 --- a/.gitlab/scripts/deploy.sh +++ b/.gitlab/scripts/deploy.sh @@ -48,20 +48,4 @@ if [ "$MODE" = "publish" ] || [ "$MODE" = "all" ]; then exit 1 fi ./gradlew -Pskip-native -Pskip-tests -Pddprof_version="${LIB_VERSION}" -PbuildInfo.build.number=$CI_JOB_ID -Pwith-libs="$(pwd)/libs" publishToSonatype closeAndReleaseSonatypeStagingRepository --exclude-task compileFuzzer --max-workers=1 --no-build-cache --stacktrace --info --no-watch-fs --no-daemon - - # Gradle's maven-publish always uploads snapshots under a unique timestamped - # filename (e.g. ddprof-1.2.3-branch-20260804.115820-1-debug.jar); there's no - # supported way to opt out of that. Some downstream consumers (e.g. the - # benchmarking-platform's downloader) fetch snapshots by the literal - # "-SNAPSHOT" filename instead of resolving maven-metadata.xml, so also - # publish plain copies of the locally-built jars under that literal name. - if [[ "${LIB_VERSION}" == *-SNAPSHOT ]]; then - echo "=== Publishing literal-named snapshot copies for non-metadata-aware consumers ===" - BASE_URL="https://central.sonatype.com/repository/maven-snapshots/com/datadoghq/ddprof/${LIB_VERSION}" - for jar in ddprof-lib/build/libs/ddprof-"${LIB_VERSION}"*.jar; do - [ -f "$jar" ] || continue - echo "Uploading $(basename "$jar")" - curl -sf -u "${SONATYPE_USERNAME}:${SONATYPE_PASSWORD}" --upload-file "$jar" "${BASE_URL}/$(basename "$jar")" - done - fi fi From 95036b99384319a5f262def3ad561fb55591a861 Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Tue, 4 Aug 2026 14:46:06 +0200 Subject: [PATCH 06/10] fix: wait for snapshot artifact to resolve via maven-metadata.xml before returning Poll the metadata.xml Sonatype indexing produces (not a nonexistent literal-named jar) so deploy-artifact doesn't return before downstream consumers can resolve the just-published snapshot. --- .gitlab/scripts/deploy.sh | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/.gitlab/scripts/deploy.sh b/.gitlab/scripts/deploy.sh index c0e74f676d..06972ba832 100755 --- a/.gitlab/scripts/deploy.sh +++ b/.gitlab/scripts/deploy.sh @@ -48,4 +48,32 @@ if [ "$MODE" = "publish" ] || [ "$MODE" = "all" ]; then exit 1 fi ./gradlew -Pskip-native -Pskip-tests -Pddprof_version="${LIB_VERSION}" -PbuildInfo.build.number=$CI_JOB_ID -Pwith-libs="$(pwd)/libs" publishToSonatype closeAndReleaseSonatypeStagingRepository --exclude-task compileFuzzer --max-workers=1 --no-build-cache --stacktrace --info --no-watch-fs --no-daemon + + # Downstream consumers (e.g. benchmarking-platform's run-benchmarks.sh) + # resolve the real timestamped filename via maven-metadata.xml right after + # this job finishes. Sonatype needs a little time to index a freshly + # published snapshot, so wait until the metadata (and the jar it points to) + # are actually resolvable before this job reports success. + if [[ "${LIB_VERSION}" == *-SNAPSHOT ]]; then + echo "=== Waiting for snapshot artifact to become resolvable on Sonatype ===" + META_URL="https://central.sonatype.com/repository/maven-snapshots/com/datadoghq/ddprof/${LIB_VERSION}/maven-metadata.xml" + RESOLVED=0 + for attempt in $(seq 1 20); do + SNAPSHOT_VER=$(curl -fsSL "${META_URL}" 2>/dev/null | grep -o '[^<]*' | tail -1 | sed 's/<[^>]*>//g' || true) + if [ -n "${SNAPSHOT_VER}" ]; then + JAR_URL="https://central.sonatype.com/repository/maven-snapshots/com/datadoghq/ddprof/${LIB_VERSION}/ddprof-${SNAPSHOT_VER}-debug.jar" + if curl -fsSL -o /dev/null "${JAR_URL}"; then + echo "Snapshot artifact resolvable: ${JAR_URL}" + RESOLVED=1 + break + fi + fi + echo "Attempt ${attempt}/20: snapshot not yet resolvable, retrying in 15s..." + sleep 15 + done + if [ "${RESOLVED}" -ne 1 ]; then + echo "ERROR: snapshot artifact still not resolvable after 20 attempts" >&2 + exit 1 + fi + fi fi From 857abc6bd55f4a3877dc615a751e1cb51ed6cc00 Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Tue, 4 Aug 2026 14:51:57 +0200 Subject: [PATCH 07/10] fix: target debug/jar classifier when parsing snapshot metadata Copilot review: grabbing the last in maven-metadata.xml could pick a different classifier's timestamp, giving false negatives. --- .gitlab/scripts/deploy.sh | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.gitlab/scripts/deploy.sh b/.gitlab/scripts/deploy.sh index 06972ba832..a18f36e197 100755 --- a/.gitlab/scripts/deploy.sh +++ b/.gitlab/scripts/deploy.sh @@ -59,7 +59,13 @@ if [ "$MODE" = "publish" ] || [ "$MODE" = "all" ]; then META_URL="https://central.sonatype.com/repository/maven-snapshots/com/datadoghq/ddprof/${LIB_VERSION}/maven-metadata.xml" RESOLVED=0 for attempt in $(seq 1 20); do - SNAPSHOT_VER=$(curl -fsSL "${META_URL}" 2>/dev/null | grep -o '[^<]*' | tail -1 | sed 's/<[^>]*>//g' || true) + SNAPSHOT_VER=$(curl -fsSL "${META_URL}" 2>/dev/null | awk ' + // { classifier=""; extension=""; value="" } + // { gsub(/<\/?classifier>/,""); gsub(/^[ \t]+|[ \t]+$/,""); classifier=$0 } + // { gsub(/<\/?extension>/,""); gsub(/^[ \t]+|[ \t]+$/,""); extension=$0 } + // { gsub(/<\/?value>/,""); gsub(/^[ \t]+|[ \t]+$/,""); value=$0 } + /<\/snapshotVersion>/ { if (classifier=="debug" && extension=="jar") print value } + ' || true) if [ -n "${SNAPSHOT_VER}" ]; then JAR_URL="https://central.sonatype.com/repository/maven-snapshots/com/datadoghq/ddprof/${LIB_VERSION}/ddprof-${SNAPSHOT_VER}-debug.jar" if curl -fsSL -o /dev/null "${JAR_URL}"; then From eb021f24f0fa6a9787529cd61f26dbd6fc9ac87d Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Tue, 4 Aug 2026 15:03:18 +0200 Subject: [PATCH 08/10] fix: update stale IBM Java 8 download URL (8.0.8.60 -> 8.0.8.70) IBM only retains the last few point releases on public.dhe.ibm.com; 8.0.8.60 was rotated out, breaking JDK setup on release/* runs. --- .github/workflows/cache_java.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cache_java.yml b/.github/workflows/cache_java.yml index 17abf88e2c..7bba69ef97 100644 --- a/.github/workflows/cache_java.yml +++ b/.github/workflows/cache_java.yml @@ -34,7 +34,7 @@ env: # jdk1.8.0_361 JAVA_8_ORACLE_URL: "https://javadl.oracle.com/webapps/download/AutoDL?BundleId=247926_0ae14417abb444ebb02b9815e2103550" - JAVA_8_IBM_URL: "https://public.dhe.ibm.com/ibmdl/export/pub/systems/cloud/runtimes/java/8.0.8.60/linux/x86_64/ibm-java-jre-8.0-8.60-linux-x86_64.tgz" + JAVA_8_IBM_URL: "https://public.dhe.ibm.com/ibmdl/export/pub/systems/cloud/runtimes/java/8.0.8.70/linux/x86_64/ibm-java-jre-8.0-8.70-linux-x86_64.tgz" # FIXME: Azul pulled public CDN access to Zing/Prime downloads - all URLs return 404 # JAVA_8_ZING_URL : "https://cdn.azul.com/zing-zvm/ZVM23.05.0.0/zing23.05.0.0-2-jdk8.0.372-linux_x64.tar.gz" From 271e8cc099bcb05219a5f8a03c2ad6ddf7840b7a Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Tue, 4 Aug 2026 16:38:50 +0200 Subject: [PATCH 09/10] refactor: dedupe release/* skip rule into shared .skip-on-release job Co-Authored-By: Claude Sonnet 5 --- .gitlab/benchmarks/.gitlab-ci.yml | 3 +-- .gitlab/build-deploy/.gitlab-ci.yml | 12 ++++-------- .gitlab/common.yml | 11 +++++++++++ .gitlab/dd-trace-integration/.gitlab-ci.yml | 12 ++++-------- 4 files changed, 20 insertions(+), 18 deletions(-) diff --git a/.gitlab/benchmarks/.gitlab-ci.yml b/.gitlab/benchmarks/.gitlab-ci.yml index 3d68ac13f2..eee8d533a1 100644 --- a/.gitlab/benchmarks/.gitlab-ci.yml +++ b/.gitlab/benchmarks/.gitlab-ci.yml @@ -17,8 +17,7 @@ benchmarks-trigger: rules: - if: '$CANCELLED == "true"' when: never - - if: '$CI_COMMIT_BRANCH =~ /^release\//' - when: never + - !reference [.skip-on-release, rules] - if: '$JDK_VERSION != null || $DEBUG_LEVEL != null || $HASH != null || $DOWNSTREAM != null' when: never - if: '$CI_PIPELINE_SOURCE == "schedule"' diff --git a/.gitlab/build-deploy/.gitlab-ci.yml b/.gitlab/build-deploy/.gitlab-ci.yml index e576e53d91..ed27bff0cd 100644 --- a/.gitlab/build-deploy/.gitlab-ci.yml +++ b/.gitlab/build-deploy/.gitlab-ci.yml @@ -218,8 +218,7 @@ build-artifact: artifacts: false optional: true rules: - - if: '$CI_COMMIT_BRANCH =~ /^release\//' - when: never + - !reference [.skip-on-release, rules] - when: on_success tags: [ "arch:amd64" ] image: ${BUILD_IMAGE_X64} @@ -254,8 +253,7 @@ deploy-artifact: - job: build:arm64-musl artifacts: true rules: - - if: '$CI_COMMIT_BRANCH =~ /^release\//' - when: never + - !reference [.skip-on-release, rules] - when: on_success tags: [ "arch:amd64" ] image: ${BUILD_IMAGE_X64} @@ -346,8 +344,7 @@ notify-slack-on-success: - job: deploy-artifact artifacts: false rules: - - if: '$CI_COMMIT_BRANCH =~ /^release\//' - when: never + - !reference [.skip-on-release, rules] - when: on_success image: registry.ddbuild.io/slack-notifier:v91289620-4ec922a-latest@sha256:06b24f392ccc383d371c72001520a254edef523bc0bfdc445f487106107b4202 tags: ["arch:amd64"] @@ -363,8 +360,7 @@ notify-slack-on-failure: - job: deploy-artifact artifacts: true rules: - - if: '$CI_COMMIT_BRANCH =~ /^release\//' - when: never + - !reference [.skip-on-release, rules] - when: on_failure image: registry.ddbuild.io/slack-notifier:v91289620-4ec922a-latest@sha256:06b24f392ccc383d371c72001520a254edef523bc0bfdc445f487106107b4202 tags: ["arch:amd64"] diff --git a/.gitlab/common.yml b/.gitlab/common.yml index 292a1462d1..b70151ee64 100644 --- a/.gitlab/common.yml +++ b/.gitlab/common.yml @@ -41,6 +41,17 @@ variables: KUBERNETES_SERVICE_ACCOUNT_OVERWRITE: java-profiler +# Skip a job on release/* branches. build-artifact/deploy-artifact don't run +# there, so anything that needs: them must also skip there or pipeline +# creation fails. Splice into a job's own rules with: +# rules: +# - !reference [.skip-on-release, rules] +# - ... +.skip-on-release: + rules: + - if: '$CI_COMMIT_BRANCH =~ /^release\//' + when: never + # Install gh and crane when not already present in the image. # Extend this in before_script for jobs that need GitHub CLI or crane. .bootstrap-gh-tools: diff --git a/.gitlab/dd-trace-integration/.gitlab-ci.yml b/.gitlab/dd-trace-integration/.gitlab-ci.yml index 5ddb457735..3d7b0ec52c 100644 --- a/.gitlab/dd-trace-integration/.gitlab-ci.yml +++ b/.gitlab/dd-trace-integration/.gitlab-ci.yml @@ -17,8 +17,7 @@ prepare-patched-agent: - job: build-artifact artifacts: true rules: - - if: '$CI_COMMIT_BRANCH =~ /^release\//' - when: never + - !reference [.skip-on-release, rules] - if: '$JDK_VERSION != null || $DEBUG_LEVEL != null || $HASH != null || $DOWNSTREAM != null' when: never - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' @@ -89,8 +88,7 @@ prepare-patched-agent: - job: prepare-patched-agent artifacts: true rules: - - if: '$CI_COMMIT_BRANCH =~ /^release\//' - when: never + - !reference [.skip-on-release, rules] - if: '$JDK_VERSION != null || $DEBUG_LEVEL != null || $HASH != null || $DOWNSTREAM != null' when: never - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' @@ -272,8 +270,7 @@ report-dd-trace-results: - job: integration-test-arm64-musl artifacts: true rules: - - if: '$CI_COMMIT_BRANCH =~ /^release\//' - when: never + - !reference [.skip-on-release, rules] - if: '$JDK_VERSION != null || $DEBUG_LEVEL != null || $HASH != null || $DOWNSTREAM != null' when: never - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' @@ -302,8 +299,7 @@ post-pr-comment: - job: integration-test-arm64-musl artifacts: true rules: - - if: '$CI_COMMIT_BRANCH =~ /^release\//' - when: never + - !reference [.skip-on-release, rules] - if: '$JDK_VERSION != null || $DEBUG_LEVEL != null || $HASH != null || $DOWNSTREAM != null' when: never - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' From 3aaae95ce863fc717b52eb31b8bf9dbfb5dee5a6 Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Wed, 5 Aug 2026 09:29:35 +0200 Subject: [PATCH 10/10] fix: guard snapshot-resolvability check against stale maven-metadata Compares against a pre-publish baseline so a lingering prior-build entry in maven-metadata.xml isn't mistaken for the freshly published snapshot; adds unit tests for the new comparison helper. Co-Authored-By: Claude Sonnet 5 --- .gitlab-ci.yml | 9 +++++ .gitlab/scripts/deploy.sh | 46 +++++++++++++++------- .gitlab/scripts/includes.sh | 6 +++ .gitlab/scripts/tests/includes_test.sh | 54 ++++++++++++++++++++++++++ 4 files changed, 102 insertions(+), 13 deletions(-) create mode 100644 .gitlab/scripts/tests/includes_test.sh diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6f44514eb7..0d3d7d9e14 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -133,6 +133,15 @@ create_key: paths: - pubkeys +# Unit tests for shared helpers in .gitlab/scripts/includes.sh (e.g. the +# snapshot-staleness check deploy.sh relies on to poll Sonatype). +shell-unit-tests: + stage: prepare + needs: [] + image: ${PREPARE_IMAGE} + script: + - bash .gitlab/scripts/tests/includes_test.sh + # Shared version detection used by benchmarks and reliability pipelines get-versions: extends: .get-versions diff --git a/.gitlab/scripts/deploy.sh b/.gitlab/scripts/deploy.sh index a18f36e197..689f51bb05 100755 --- a/.gitlab/scripts/deploy.sh +++ b/.gitlab/scripts/deploy.sh @@ -40,6 +40,22 @@ if [ "$MODE" = "assemble" ] || [ "$MODE" = "all" ]; then ./gradlew -Pskip-native -Pskip-tests -Pddprof_version="${LIB_VERSION}" -PbuildInfo.build.number=$CI_JOB_ID -Pwith-libs="$(pwd)/libs" :ddprof-lib:jar assembleAll --exclude-task compileFuzzer --exclude-task sign --max-workers=1 --no-build-cache --stacktrace --info --no-watch-fs --no-daemon fi +# Resolve the debug/jar classifier's timestamped version from a snapshot's +# maven-metadata.xml. Only the last matching block is +# honored so a metadata file listing the same classifier/extension pair more +# than once can't produce multiple version lines from a single lookup. +CURL_TIMEOUT_OPTS=(--connect-timeout 10 --max-time 30) +get_debug_jar_snapshot_version() { + curl -fsSL "${CURL_TIMEOUT_OPTS[@]}" "$1" 2>/dev/null | awk ' + // { classifier=""; extension=""; value="" } + // { gsub(/<\/?classifier>/,""); gsub(/^[ \t]+|[ \t]+$/,""); classifier=$0 } + // { gsub(/<\/?extension>/,""); gsub(/^[ \t]+|[ \t]+$/,""); extension=$0 } + // { gsub(/<\/?value>/,""); gsub(/^[ \t]+|[ \t]+$/,""); value=$0 } + /<\/snapshotVersion>/ { if (classifier=="debug" && extension=="jar") last=value } + END { print last } + ' || true +} + # Publish task (only when publishing to Maven Central) if [ "$MODE" = "publish" ] || [ "$MODE" = "all" ]; then echo "=== Publishing to Sonatype ===" @@ -47,38 +63,42 @@ if [ "$MODE" = "publish" ] || [ "$MODE" = "all" ]; then echo "ERROR: GPG_PRIVATE_KEY is not set — run the create_key CI job first to provision the signing key in SSM (ci.java-profiler.signing.gpg_private_key)" exit 1 fi + META_URL="https://central.sonatype.com/repository/maven-snapshots/com/datadoghq/ddprof/${LIB_VERSION}/maven-metadata.xml" + # Record whatever debug/jar version is resolvable *before* publishing so the + # post-publish wait below can tell the freshly uploaded build apart from a + # preceding one that Sonatype hasn't finished replacing in the metadata yet. + PRE_PUBLISH_SNAPSHOT_VER="" + if [[ "${LIB_VERSION}" == *-SNAPSHOT ]]; then + PRE_PUBLISH_SNAPSHOT_VER=$(get_debug_jar_snapshot_version "${META_URL}") + fi + ./gradlew -Pskip-native -Pskip-tests -Pddprof_version="${LIB_VERSION}" -PbuildInfo.build.number=$CI_JOB_ID -Pwith-libs="$(pwd)/libs" publishToSonatype closeAndReleaseSonatypeStagingRepository --exclude-task compileFuzzer --max-workers=1 --no-build-cache --stacktrace --info --no-watch-fs --no-daemon # Downstream consumers (e.g. benchmarking-platform's run-benchmarks.sh) # resolve the real timestamped filename via maven-metadata.xml right after # this job finishes. Sonatype needs a little time to index a freshly # published snapshot, so wait until the metadata (and the jar it points to) - # are actually resolvable before this job reports success. + # are actually resolvable before this job reports success. A version that + # matches PRE_PUBLISH_SNAPSHOT_VER is rejected: that's the preceding build's + # entry still lingering in the metadata, not the one just uploaded. if [[ "${LIB_VERSION}" == *-SNAPSHOT ]]; then echo "=== Waiting for snapshot artifact to become resolvable on Sonatype ===" - META_URL="https://central.sonatype.com/repository/maven-snapshots/com/datadoghq/ddprof/${LIB_VERSION}/maven-metadata.xml" RESOLVED=0 for attempt in $(seq 1 20); do - SNAPSHOT_VER=$(curl -fsSL "${META_URL}" 2>/dev/null | awk ' - // { classifier=""; extension=""; value="" } - // { gsub(/<\/?classifier>/,""); gsub(/^[ \t]+|[ \t]+$/,""); classifier=$0 } - // { gsub(/<\/?extension>/,""); gsub(/^[ \t]+|[ \t]+$/,""); extension=$0 } - // { gsub(/<\/?value>/,""); gsub(/^[ \t]+|[ \t]+$/,""); value=$0 } - /<\/snapshotVersion>/ { if (classifier=="debug" && extension=="jar") print value } - ' || true) - if [ -n "${SNAPSHOT_VER}" ]; then + SNAPSHOT_VER=$(get_debug_jar_snapshot_version "${META_URL}") + if is_new_snapshot_version "${SNAPSHOT_VER}" "${PRE_PUBLISH_SNAPSHOT_VER}"; then JAR_URL="https://central.sonatype.com/repository/maven-snapshots/com/datadoghq/ddprof/${LIB_VERSION}/ddprof-${SNAPSHOT_VER}-debug.jar" - if curl -fsSL -o /dev/null "${JAR_URL}"; then + if curl -fsSL "${CURL_TIMEOUT_OPTS[@]}" -o /dev/null "${JAR_URL}"; then echo "Snapshot artifact resolvable: ${JAR_URL}" RESOLVED=1 break fi fi - echo "Attempt ${attempt}/20: snapshot not yet resolvable, retrying in 15s..." + echo "Attempt ${attempt}/20: newly published snapshot not yet resolvable, retrying in 15s..." sleep 15 done if [ "${RESOLVED}" -ne 1 ]; then - echo "ERROR: snapshot artifact still not resolvable after 20 attempts" >&2 + echo "ERROR: newly published snapshot artifact still not resolvable after 20 attempts" >&2 exit 1 fi fi diff --git a/.gitlab/scripts/includes.sh b/.gitlab/scripts/includes.sh index 676b4f29e4..dc40094d72 100755 --- a/.gitlab/scripts/includes.sh +++ b/.gitlab/scripts/includes.sh @@ -53,6 +53,12 @@ function setup_java_home() { echo "Using Java @ ${JAVA_HOME}" } +function is_new_snapshot_version() { + local candidate="$1" + local baseline="$2" + [ -n "${candidate}" ] && [ "${candidate}" != "${baseline}" ] +} + function collect_artifacts() { local target=$1 local artifact_type=$2 # "test" or "stresstest" diff --git a/.gitlab/scripts/tests/includes_test.sh b/.gitlab/scripts/tests/includes_test.sh new file mode 100644 index 0000000000..93a08a3d87 --- /dev/null +++ b/.gitlab/scripts/tests/includes_test.sh @@ -0,0 +1,54 @@ +#! /bin/bash +# Minimal, dependency-free unit tests for .gitlab/scripts/includes.sh helpers. +# Run with: bash .gitlab/scripts/tests/includes_test.sh + +set -eo pipefail + +HERE=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +source "${HERE}/../includes.sh" + +FAILED=0 + +assert_true() { + local desc="$1" + shift + if "$@"; then + echo "PASS: ${desc}" + else + echo "FAIL: ${desc} — expected success" + FAILED=1 + fi +} + +assert_false() { + local desc="$1" + shift + if "$@"; then + echo "FAIL: ${desc} — expected failure" + FAILED=1 + else + echo "PASS: ${desc}" + fi +} + +# A freshly published snapshot version differs from the pre-publish baseline +# and must be accepted. +assert_true "differing candidate is accepted as new" \ + is_new_snapshot_version "20260101.120000-5" "20260101.100000-3" + +# The metadata still pointing at the pre-publish baseline is stale and must +# be rejected — this is the guard the retry loop in deploy.sh relies on. +assert_false "candidate matching baseline is rejected as stale" \ + is_new_snapshot_version "20260101.100000-3" "20260101.100000-3" + +# An empty candidate (metadata not resolvable yet) must be rejected +# regardless of the baseline. +assert_false "empty candidate is rejected" \ + is_new_snapshot_version "" "20260101.100000-3" + +# An empty baseline (no prior publish) plus any non-empty candidate must be +# accepted. +assert_true "non-empty candidate with empty baseline is accepted" \ + is_new_snapshot_version "20260101.120000-5" "" + +exit "${FAILED}"