From 69e91e6a53d785a4084c9fa05fef0fe32249dfab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chojnacki?= Date: Wed, 18 Mar 2026 20:42:33 +0100 Subject: [PATCH 01/16] Integrate one-pipeline for standardized OCI packaging and CI hardening --- .gitlab-ci.yml | 49 +++++++++++-- .gitlab/build-and-test-all.yml | 106 ++++++++++++++++++++++++++++ .gitlab/build-and-test-fast.yml | 11 ++- .gitlab/common.yml | 18 +++-- .gitlab/one-pipeline.locked.yml | 4 ++ .gitlab/prepare-oci-package.sh | 40 +++++++++++ .gitlab/ssi-package.yml | 61 ++++++++++++++++ Makefile | 1 + metadata/requirements-allow.json | 30 ++++++++ metadata/requirements-block.json | 1 + packaging/sources/requirements.json | 31 ++++++++ 11 files changed, 341 insertions(+), 11 deletions(-) create mode 100644 .gitlab/one-pipeline.locked.yml create mode 100755 .gitlab/prepare-oci-package.sh create mode 100644 .gitlab/ssi-package.yml create mode 100644 metadata/requirements-allow.json create mode 100644 metadata/requirements-block.json create mode 100644 packaging/sources/requirements.json diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 34f6d0c5..47160e3d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -3,18 +3,57 @@ workflow: auto_cancel: on_new_commit: interruptible +default: + interruptible: true + +include: + - local: ".gitlab/build-and-test-all.yml" + - local: ".gitlab/build-and-test-fast.yml" + - local: ".gitlab/ssi-package.yml" + - local: ".gitlab/one-pipeline.locked.yml" + +variables: + OCI_PACKAGE_NAME: datadog-nginx-ssi + OCI_AGENT_REGISTRY_PACKAGE_NAME: apm-library-nginx-package + AGENT_REPO_PRODUCT_NAME: nginx_datadog + LIB_INJECTION_NAME: dd-lib-nginx-init + REPO_NOTIFICATION_CHANNEL: "#injection-platform" + stages: - build-and-test-fast - build-all - test-all + - build + - shared-pipeline - benchmarks -default: - interruptible: true +requirements_json_test: + rules: + - when: on_success + variables: + REQUIREMENTS_BLOCK_JSON_PATH: "metadata/requirements-block.json" + REQUIREMENTS_ALLOW_JSON_PATH: "metadata/requirements-allow.json" -include: - - local: ".gitlab/build-and-test-all.yml" - - local: ".gitlab/build-and-test-fast.yml" +package-oci: + # Both ssi-build jobs are optional because only one runs per pipeline type. + # prepare-oci-package.sh validates that the ssi-sources directory for the + # target architecture exists, and exits 1 if missing. + needs: + - job: ssi-build + optional: true + - job: ssi-build-all + optional: true + +# TODO: Re-enable when adding k8s injection support. +# Requires ci.nginx-datadog.apm-ecosystems-reliability-profile SSM parameter +# in AWS us-east-1 (ask infra/platform team to create it). +kubernetes-injection-test-ecr-publish: + allow_failure: true + +configure_system_tests: + variables: + SYSTEM_TESTS_LIBRARY: cpp_nginx + SYSTEM_TESTS_SCENARIOS_GROUPS: "docker-ssi" macrobenchmarks: stage: benchmarks diff --git a/.gitlab/build-and-test-all.yml b/.gitlab/build-and-test-all.yml index 8ae52a9a..3f702150 100644 --- a/.gitlab/build-and-test-all.yml +++ b/.gitlab/build-and-test-all.yml @@ -5,6 +5,7 @@ include: # with more than 100 jobs! .build-and-test-all: + extends: .git-config rules: - if: $CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+\.[0-9]+/ when: always @@ -64,10 +65,31 @@ build-nginx-rum-all: - ARCH: ["amd64", "arm64"] NGINX_VERSION: - "1.24.0" + - "1.25.0" + - "1.25.1" + - "1.25.2" + - "1.25.3" + - "1.25.4" - "1.25.5" + - "1.26.0" + - "1.26.1" + - "1.26.2" - "1.26.3" + - "1.27.0" + - "1.27.1" + - "1.27.2" + - "1.27.3" + - "1.27.4" - "1.27.5" + - "1.28.0" + - "1.28.1" - "1.28.2" + - "1.29.0" + - "1.29.1" + - "1.29.2" + - "1.29.3" + - "1.29.4" + - "1.29.5" - "1.29.6" WAF: ["OFF"] @@ -272,22 +294,106 @@ test-nginx-rum-all: BASE_IMAGE: ["nginx:1.24.0"] NGINX_VERSION: ["1.24.0"] WAF: ["OFF"] + - ARCH: ["amd64", "arm64"] + BASE_IMAGE: ["nginx:1.25.0"] + NGINX_VERSION: ["1.25.0"] + WAF: ["OFF"] + - ARCH: ["amd64", "arm64"] + BASE_IMAGE: ["nginx:1.25.1"] + NGINX_VERSION: ["1.25.1"] + WAF: ["OFF"] + - ARCH: ["amd64", "arm64"] + BASE_IMAGE: ["nginx:1.25.2"] + NGINX_VERSION: ["1.25.2"] + WAF: ["OFF"] + - ARCH: ["amd64", "arm64"] + BASE_IMAGE: ["nginx:1.25.3"] + NGINX_VERSION: ["1.25.3"] + WAF: ["OFF"] + - ARCH: ["amd64", "arm64"] + BASE_IMAGE: ["nginx:1.25.4"] + NGINX_VERSION: ["1.25.4"] + WAF: ["OFF"] - ARCH: ["amd64", "arm64"] BASE_IMAGE: ["nginx:1.25.5"] NGINX_VERSION: ["1.25.5"] WAF: ["OFF"] + - ARCH: ["amd64", "arm64"] + BASE_IMAGE: ["nginx:1.26.0"] + NGINX_VERSION: ["1.26.0"] + WAF: ["OFF"] + - ARCH: ["amd64", "arm64"] + BASE_IMAGE: ["nginx:1.26.1"] + NGINX_VERSION: ["1.26.1"] + WAF: ["OFF"] + - ARCH: ["amd64", "arm64"] + BASE_IMAGE: ["nginx:1.26.2"] + NGINX_VERSION: ["1.26.2"] + WAF: ["OFF"] - ARCH: ["amd64", "arm64"] BASE_IMAGE: ["nginx:1.26.3"] NGINX_VERSION: ["1.26.3"] WAF: ["OFF"] + - ARCH: ["amd64", "arm64"] + BASE_IMAGE: ["nginx:1.27.0"] + NGINX_VERSION: ["1.27.0"] + WAF: ["OFF"] + - ARCH: ["amd64", "arm64"] + BASE_IMAGE: ["nginx:1.27.1"] + NGINX_VERSION: ["1.27.1"] + WAF: ["OFF"] + - ARCH: ["amd64", "arm64"] + BASE_IMAGE: ["nginx:1.27.2"] + NGINX_VERSION: ["1.27.2"] + WAF: ["OFF"] + - ARCH: ["amd64", "arm64"] + BASE_IMAGE: ["nginx:1.27.3"] + NGINX_VERSION: ["1.27.3"] + WAF: ["OFF"] + - ARCH: ["amd64", "arm64"] + BASE_IMAGE: ["nginx:1.27.4"] + NGINX_VERSION: ["1.27.4"] + WAF: ["OFF"] - ARCH: ["amd64", "arm64"] BASE_IMAGE: ["nginx:1.27.5"] NGINX_VERSION: ["1.27.5"] WAF: ["OFF"] + - ARCH: ["amd64", "arm64"] + BASE_IMAGE: ["nginx:1.28.0"] + NGINX_VERSION: ["1.28.0"] + WAF: ["OFF"] + - ARCH: ["amd64", "arm64"] + BASE_IMAGE: ["nginx:1.28.1"] + NGINX_VERSION: ["1.28.1"] + WAF: ["OFF"] - ARCH: ["amd64", "arm64"] BASE_IMAGE: ["nginx:1.28.2"] NGINX_VERSION: ["1.28.2"] WAF: ["OFF"] + - ARCH: ["amd64", "arm64"] + BASE_IMAGE: ["nginx:1.29.0"] + NGINX_VERSION: ["1.29.0"] + WAF: ["OFF"] + - ARCH: ["amd64", "arm64"] + BASE_IMAGE: ["nginx:1.29.1"] + NGINX_VERSION: ["1.29.1"] + WAF: ["OFF"] + - ARCH: ["amd64", "arm64"] + BASE_IMAGE: ["nginx:1.29.2"] + NGINX_VERSION: ["1.29.2"] + WAF: ["OFF"] + - ARCH: ["amd64", "arm64"] + BASE_IMAGE: ["nginx:1.29.3"] + NGINX_VERSION: ["1.29.3"] + WAF: ["OFF"] + - ARCH: ["amd64", "arm64"] + BASE_IMAGE: ["nginx:1.29.4"] + NGINX_VERSION: ["1.29.4"] + WAF: ["OFF"] + - ARCH: ["amd64", "arm64"] + BASE_IMAGE: ["nginx:1.29.5"] + NGINX_VERSION: ["1.29.5"] + WAF: ["OFF"] - ARCH: ["amd64", "arm64"] BASE_IMAGE: ["nginx:1.29.6"] NGINX_VERSION: ["1.29.6"] diff --git a/.gitlab/build-and-test-fast.yml b/.gitlab/build-and-test-fast.yml index 844ad228..96c54963 100644 --- a/.gitlab/build-and-test-fast.yml +++ b/.gitlab/build-and-test-fast.yml @@ -2,6 +2,7 @@ include: - local: ".gitlab/common.yml" .build-and-test-fast: + extends: .git-config stage: build-and-test-fast rules: - if: $CI_COMMIT_TAG @@ -42,7 +43,7 @@ shellcheck: image: $CI_REGISTRY/nginx_musl_toolchain tags: ["arch:amd64"] script: - - find bin/ test/ example/ -type f -executable -not -name '*.py' | xargs shellcheck --exclude SC1071,SC1091,SC2317 + - find bin/ test/ example/ .gitlab/ \( -type f -executable -not -name '*.py' \) -o \( -name '*.sh' -type f \) | xargs shellcheck --exclude SC1071,SC1091,SC2317 build-nginx-fast: extends: @@ -99,6 +100,7 @@ build-nginx-rum-fast: - "1.26.3" - "1.27.5" - "1.28.2" + - "1.29.5" - "1.29.6" WAF: ["OFF"] @@ -195,6 +197,10 @@ test-nginx-rum-fast: BASE_IMAGE: ["nginx:1.28.2"] NGINX_VERSION: ["1.28.2"] WAF: ["OFF"] + - ARCH: ["amd64", "arm64"] + BASE_IMAGE: ["nginx:1.29.5"] + NGINX_VERSION: ["1.29.5"] + WAF: ["OFF"] - ARCH: ["amd64", "arm64"] BASE_IMAGE: ["nginx:1.29.6"] NGINX_VERSION: ["1.29.6"] @@ -210,5 +216,8 @@ coverage: NGINX_VERSION: "1.26.0" WAF: "ON" tags: ["docker-in-docker:$ARCH"] + retry: + max: 2 + when: script_failure script: - make coverage diff --git a/.gitlab/common.yml b/.gitlab/common.yml index 8188144d..3bcc1a56 100644 --- a/.gitlab/common.yml +++ b/.gitlab/common.yml @@ -1,13 +1,20 @@ variables: CI_REGISTRY: "registry.ddbuild.io/ci/nginx-datadog" TESTS_IMAGES_REGISTRY: "$CI_REGISTRY/mirror" - GIT_SUBMODULE_STRATEGY: recursive - GIT_SUBMODULE_DEPTH: 1 - GIT_CONFIG_COUNT: 1 - GIT_CONFIG_KEY_0: url.https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.ddbuild.io/DataDog/.insteadOf - GIT_CONFIG_VALUE_0: https://github.com/DataDog/ + +# Git config for repo-defined jobs: submodule cloning and GitHub→GitLab URL +# rewriting via CI job token. Defined as a hidden job (not global) so +# 3rd-party includes (one-pipeline) don't inherit the rewrite. +.git-config: + variables: + GIT_SUBMODULE_STRATEGY: recursive + GIT_SUBMODULE_DEPTH: 1 + GIT_CONFIG_COUNT: 1 + GIT_CONFIG_KEY_0: url.https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.ddbuild.io/DataDog/.insteadOf + GIT_CONFIG_VALUE_0: https://github.com/DataDog/ .build: + extends: .git-config image: $CI_REGISTRY/nginx_musl_toolchain tags: ["arch:$ARCH"] variables: @@ -60,6 +67,7 @@ variables: - artifacts-ingress/$ARCH/$INGRESS_NGINX_VERSION/ .test: + extends: .git-config image: $CI_REGISTRY/test tags: ["docker-in-docker:$ARCH"] diff --git a/.gitlab/one-pipeline.locked.yml b/.gitlab/one-pipeline.locked.yml new file mode 100644 index 00000000..3e1f1a62 --- /dev/null +++ b/.gitlab/one-pipeline.locked.yml @@ -0,0 +1,4 @@ +# DO NOT EDIT THIS FILE MANUALLY +# This file is auto-generated by automation. +include: + - remote: https://gitlab-templates.ddbuild.io/libdatadog/one-pipeline/ca/f14ac28614630d12bcfe6cba4fd8d72dce142c62ff0b053ba7c323622104ebd7/one-pipeline.yml diff --git a/.gitlab/prepare-oci-package.sh b/.gitlab/prepare-oci-package.sh new file mode 100755 index 00000000..b8939fa5 --- /dev/null +++ b/.gitlab/prepare-oci-package.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +# Called by one-pipeline's package-oci job to populate the sources/ directory +# that datadog-package create expects. +# +# Assumes CWD is set by the package-oci job (a subdirectory of the repo root, +# so ../artifacts/ resolves to the ssi-build artifact directory). +# +# The ssi-build / ssi-build-all CI jobs collect RUM-enabled nginx modules from +# build-nginx-rum-fast / build-nginx-rum-all and assemble them into +# artifacts/ssi-sources//. This script copies those artifacts into +# sources/ for OCI packaging. + +set -euo pipefail + +if [ -z "${ARCH}" ]; then + echo "ARCH not available as an environment variable" + exit 1 +fi + +SOURCES_DIR="../artifacts/ssi-sources/${ARCH}" + +if [ ! -d "${SOURCES_DIR}" ]; then + echo "ERROR: Sources directory not found: ${SOURCES_DIR} (pwd: $(pwd))" + echo "The ssi-build or ssi-build-all job must complete before package-oci runs." + exit 1 +fi + +echo "Copying sources from ${SOURCES_DIR} to sources/" +mkdir -p sources +cp -r "${SOURCES_DIR}/"* sources/ + +so_count=$(find sources -name '*.so' -type f | wc -l) +if [ "$so_count" -eq 0 ]; then + echo "ERROR: No .so module files found in sources/ after copy from ${SOURCES_DIR}" + exit 1 +fi + +echo "Sources contents:" +find sources -type f | sort diff --git a/.gitlab/ssi-package.yml b/.gitlab/ssi-package.yml new file mode 100644 index 00000000..61a4b811 --- /dev/null +++ b/.gitlab/ssi-package.yml @@ -0,0 +1,61 @@ +# Assembles RUM-enabled nginx modules (built by build-nginx-rum-* jobs) into +# the directory layout expected by prepare-oci-package.sh / package-oci. +# +# Input (from build-nginx-rum-fast/all artifacts): +# artifacts-rum/$ARCH/$NGINX_VERSION/OFF/ngx_http_datadog_module.so +# +# Output (consumed by prepare-oci-package.sh): +# artifacts/ssi-sources/$ARCH/nginx/$NGINX_VERSION/ngx_http_datadog_module.so +# artifacts/ssi-sources/$ARCH/version + +.ssi-assemble: + extends: .git-config + image: registry.ddbuild.io/ci/nginx-datadog/nginx_musl_toolchain + stage: build + parallel: + matrix: + - ARCH: ["amd64", "arm64"] + tags: ["arch:amd64"] + script: + - set -euo pipefail + - VERSION="${CI_COMMIT_TAG:-0.0.1-${CI_COMMIT_SHORT_SHA}}" + - OUTPUT="artifacts/ssi-sources/${ARCH}" + - mkdir -p "${OUTPUT}" + - | + shopt -s nullglob + dirs=(artifacts-rum/${ARCH}/*/OFF) + if [ ${#dirs[@]} -eq 0 ]; then + echo "ERROR: No artifacts found at artifacts-rum/${ARCH}/*/OFF" + exit 1 + fi + for dir in "${dirs[@]}"; do + nginx_ver="$(basename "$(dirname "$dir")")" + so_file="$dir/ngx_http_datadog_module.so" + if [ ! -f "$so_file" ]; then + echo "ERROR: Module not found: $so_file (nginx: $nginx_ver, arch: $ARCH)" + exit 1 + fi + mkdir -p "${OUTPUT}/nginx/${nginx_ver}" + cp "$so_file" "${OUTPUT}/nginx/${nginx_ver}/" + done + - echo "${VERSION}" > "${OUTPUT}/version" + - echo "Assembled modules:" && find "${OUTPUT}" -type f | sort + artifacts: + paths: + - artifacts/ssi-sources/ + +ssi-build: + extends: .ssi-assemble + needs: [build-nginx-rum-fast] + rules: + - if: $CI_COMMIT_TAG + when: never + - when: always + +ssi-build-all: + extends: .ssi-assemble + needs: [build-nginx-rum-all] + rules: + - if: $CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+\.[0-9]+/ + when: always + - when: never diff --git a/Makefile b/Makefile index 456cb372..f6a4ad15 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,7 @@ RUM ?= OFF WAF ?= OFF ARCH ?= $(shell arch) +# Normalize architecture names: CI uses amd64/arm64, build tools expect x86_64/aarch64 ifeq ($(ARCH),amd64) ARCH := x86_64 endif diff --git a/metadata/requirements-allow.json b/metadata/requirements-allow.json new file mode 100644 index 00000000..5998f91d --- /dev/null +++ b/metadata/requirements-allow.json @@ -0,0 +1,30 @@ +[ + { + "name": "should allow nginx", + "filepath": "/usr/sbin/nginx", + "args": ["nginx", "-g", "daemon off;"], + "envars": [], + "host": {"os": "linux", "arch": "x64", "libc": "glibc:2.17"} + }, + { + "name": "should allow nginx on arm64", + "filepath": "/usr/sbin/nginx", + "args": ["nginx", "-g", "daemon off;"], + "envars": [], + "host": {"os": "linux", "arch": "arm64", "libc": "glibc:2.17"} + }, + { + "name": "should allow nginx with musl", + "filepath": "/usr/sbin/nginx", + "args": ["nginx"], + "envars": [], + "host": {"os": "linux", "arch": "x64", "libc": "musl"} + }, + { + "name": "should allow nginx with musl on arm64", + "filepath": "/usr/sbin/nginx", + "args": ["nginx"], + "envars": [], + "host": {"os": "linux", "arch": "arm64", "libc": "musl"} + } +] diff --git a/metadata/requirements-block.json b/metadata/requirements-block.json new file mode 100644 index 00000000..fe51488c --- /dev/null +++ b/metadata/requirements-block.json @@ -0,0 +1 @@ +[] diff --git a/packaging/sources/requirements.json b/packaging/sources/requirements.json new file mode 100644 index 00000000..645b6e66 --- /dev/null +++ b/packaging/sources/requirements.json @@ -0,0 +1,31 @@ +{ + "$schema": "https://raw.githubusercontent.com/DataDog/auto_inject/refs/heads/main/preload_go/cmd/library_requirements_tester/testdata/requirements_schema.json", + "version": 1, + "native_deps": { + "glibc": [ + { + "arch": "x64", + "supported": true, + "description": "nginx modules are built against musl, loaded into stock nginx on glibc systems" + }, + { + "arch": "arm64", + "supported": true, + "description": "nginx modules are built against musl, loaded into stock nginx on glibc systems" + } + ], + "musl": [ + { + "arch": "x64", + "supported": true, + "description": "nginx modules are built against musl for alpine-based nginx" + }, + { + "arch": "arm64", + "supported": true, + "description": "nginx modules are built against musl for alpine-based nginx" + } + ] + }, + "deny": [] +} From b1b9fa06cfae04dca875dbbc78c664324e4c664f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chojnacki?= Date: Thu, 19 Mar 2026 13:38:42 +0100 Subject: [PATCH 02/16] Trigger pipeline From e0797aa65fa82b6993978719f32a11ebe5a62a95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chojnacki?= Date: Thu, 19 Mar 2026 16:37:28 +0100 Subject: [PATCH 03/16] Trigger pipeline From 2555f70dd4aa504e80d0bfe436c96ea762c8b88b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chojnacki?= Date: Fri, 20 Mar 2026 10:14:05 +0100 Subject: [PATCH 04/16] Rename OCI_PACKAGE_NAME to datadog-apm-library-nginx --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 47160e3d..45f93467 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -13,7 +13,7 @@ include: - local: ".gitlab/one-pipeline.locked.yml" variables: - OCI_PACKAGE_NAME: datadog-nginx-ssi + OCI_PACKAGE_NAME: datadog-apm-library-nginx OCI_AGENT_REGISTRY_PACKAGE_NAME: apm-library-nginx-package AGENT_REPO_PRODUCT_NAME: nginx_datadog LIB_INJECTION_NAME: dd-lib-nginx-init From 1926b7797d1b92e45c00a264309159e0fff88395 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chojnacki?= Date: Fri, 20 Mar 2026 11:57:23 +0100 Subject: [PATCH 05/16] Revert OCI_PACKAGE_NAME to datadog-nginx-ssi --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 45f93467..47160e3d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -13,7 +13,7 @@ include: - local: ".gitlab/one-pipeline.locked.yml" variables: - OCI_PACKAGE_NAME: datadog-apm-library-nginx + OCI_PACKAGE_NAME: datadog-nginx-ssi OCI_AGENT_REGISTRY_PACKAGE_NAME: apm-library-nginx-package AGENT_REPO_PRODUCT_NAME: nginx_datadog LIB_INJECTION_NAME: dd-lib-nginx-init From b8411e5928e5df0c52c36a193f93bd2d3b6f2f75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chojnacki?= Date: Fri, 20 Mar 2026 16:29:59 +0100 Subject: [PATCH 06/16] Use stable config for RUM snippet creation and directive seeding - Auto path: try_build_snippet_from_env now uses snippet_create_from_stable_config to read from application_monitoring.yaml instead of building JSON from DD_RUM_* env vars - Directive path: on_datadog_rum_config seeds from stable config via stable_config_get_entries, with directive block values overriding - Trim env var forwarding to only DD_RUM_ENABLED and DD_RUM_APPLICATION_ID - Pin inject-browser-sdk to 587b071 (includes stable_config_get_entries FFI) --- deps/CMakeLists.txt | 5 ++- src/rum/config.cpp | 72 +++++++++++++++++++++++++-------------- src/rum/config_internal.h | 2 ++ 3 files changed, 53 insertions(+), 26 deletions(-) diff --git a/deps/CMakeLists.txt b/deps/CMakeLists.txt index 87fc5e4d..f2d8f81e 100644 --- a/deps/CMakeLists.txt +++ b/deps/CMakeLists.txt @@ -1,8 +1,11 @@ include(FetchContent) -set(INJECT_BROWSER_SDK_GIT_REF "49245e1c6ed8275990bb910125187e0aaad09e3d" CACHE STRING +set(INJECT_BROWSER_SDK_GIT_REF "587b071" CACHE STRING "Git tag/branch for inject-browser-sdk") +set(INJECT_BROWSER_SDK_NO_DEFAULT_FEATURES OFF CACHE BOOL + "Build inject-browser-sdk without default features") + FetchContent_Declare( InjectBrowserSDK GIT_REPOSITORY https://github.com/DataDog/inject-browser-sdk.git diff --git a/src/rum/config.cpp b/src/rum/config.cpp index d109722e..bc50ff8f 100644 --- a/src/rum/config.cpp +++ b/src/rum/config.cpp @@ -41,6 +41,35 @@ rum_config_map get_rum_config_from_env() { return config; } +rum_config_map get_rum_config_from_stable_config() { + rum_config_map config; + + auto entries = std::unique_ptr( + stable_config_get_entries("browser-sdk", false), + stable_config_entries_cleanup); + + if (entries == nullptr || entries->error_code) { + return config; + } + + for (uint32_t i = 0; i < entries->count; ++i) { + const char* name = entries->entries[i].name; + const char* value = entries->entries[i].value; + if (name == nullptr || value == nullptr || value[0] == '\0') continue; + + std::string_view name_sv(name); + for (const auto& [env_name, config_key] : rum_env_mappings) { + if (name_sv == env_name) { + config[std::string(config_key)] = {std::string(value)}; + break; + } + } + } + + return config; +} + std::optional get_rum_enabled_from_env() { const char* value = std::getenv("DD_RUM_ENABLED"); if (value == nullptr || value[0] == '\0') { @@ -209,7 +238,7 @@ char* on_datadog_rum_config(ngx_conf_t* cf, ngx_command_t* command, arg1_str.c_str()); } - auto rum_config = get_rum_config_from_env(); + auto rum_config = get_rum_config_from_stable_config(); ngx_conf_t save = *cf; cf->handler = set_config; @@ -244,37 +273,33 @@ char* on_datadog_rum_config(ngx_conf_t* cf, ngx_command_t* command, void try_build_snippet_from_env(ngx_conf_t* cf, datadog::nginx::datadog_loc_conf_t* loc_conf) { try { - auto env_config = get_rum_config_from_env(); - if (env_config.empty()) return; - - auto json = make_rum_json_config(default_rum_config_version, env_config); - if (json.empty()) { - ngx_log_error( - NGX_LOG_WARN, cf->log, 0, - "nginx-datadog: DD_RUM_* environment variables were set but " - "JSON config generation produced an empty result"); - return; - } - auto snippet = std::unique_ptr( - snippet_create_from_json(json.c_str()), snippet_cleanup); + snippet_create_from_stable_config("browser-sdk", false), + snippet_cleanup); + if (snippet == nullptr || snippet->error_code) { ngx_log_error(NGX_LOG_WARN, cf->log, 0, "nginx-datadog: failed to create RUM snippet from " - "environment variables: %s", + "stable config: %s", snippet ? snippet->error_message : "null snippet"); return; } loc_conf->rum_snippet = snippet.release(); - apply_rum_config_tags(loc_conf, env_config); + // Telemetry tags: best-effort from env (snippet is opaque) + const char* app_id = std::getenv("DD_RUM_APPLICATION_ID"); + if (app_id && app_id[0] != '\0') { + loc_conf->rum_application_id_tag = + std::string("application_id:") + app_id; + } + loc_conf->rum_remote_config_tag = "remote_config_used:false"; } catch (const std::bad_alloc&) { throw; - } catch (const std::exception& exception) { - ngx_log_error(NGX_LOG_WARN, cf->log, 0, - "nginx-datadog: failed to build RUM snippet from environment " - "variables: %s", - exception.what()); + } catch (const std::exception& e) { + ngx_log_error( + NGX_LOG_WARN, cf->log, 0, + "nginx-datadog: failed to build RUM snippet from stable config: %s", + e.what()); } } @@ -346,11 +371,8 @@ char* datadog_rum_merge_loc_config(ngx_conf_t* cf, std::vector get_environment_variable_names() { std::vector names; - names.reserve(rum_env_mappings.size() + 1); names.push_back("DD_RUM_ENABLED"sv); - for (const auto& [env_name, config_key] : rum_env_mappings) { - names.push_back(env_name); - } + names.push_back("DD_RUM_APPLICATION_ID"sv); // for telemetry tags return names; } diff --git a/src/rum/config_internal.h b/src/rum/config_internal.h index 76ad854a..87c499cc 100644 --- a/src/rum/config_internal.h +++ b/src/rum/config_internal.h @@ -41,6 +41,8 @@ using rum_config_map = rum_config_map get_rum_config_from_env(); +rum_config_map get_rum_config_from_stable_config(); + std::optional get_rum_enabled_from_env(); std::string make_rum_json_config(int config_version, From 479dbb7930893c4a7701d7d93f63d907efa54df7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chojnacki?= Date: Fri, 20 Mar 2026 18:00:22 +0100 Subject: [PATCH 07/16] Bump Rust toolchain to 1.85.0 in build image A transitive dependency (clap_builder 4.6.0, via libdd-library-config) now requires the Rust 2024 edition which needs Rust 1.85+. --- build_env/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build_env/Dockerfile b/build_env/Dockerfile index 53d0b190..b845e99b 100644 --- a/build_env/Dockerfile +++ b/build_env/Dockerfile @@ -76,7 +76,7 @@ RUN apk add --no-cache openssl-dev pcre-dev pcre2-dev perl zlib-dev # Rust toolchain RUN apk add --no-cache curl -RUN curl --proto '=https' –tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -yq --default-toolchain 1.73.0 && \ +RUN curl --proto '=https' –tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -yq --default-toolchain 1.85.0 && \ ln -s ~/.cargo/bin/cargo /usr/bin/cargo RUN cargo install --locked cbindgen --version 0.26.0 && \ From 9294b93f2785f5a7b3d8328be0ae824e1aa0882f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chojnacki?= Date: Fri, 20 Mar 2026 19:09:45 +0100 Subject: [PATCH 08/16] Pin CI image to nginx_musl_toolchain:rust-1.85 tag The :latest tag was cached by nydus snapshotter on CI runners. Use an explicit tag to force pulling the updated image with Rust 1.85.0. --- .gitlab/build-and-test-fast.yml | 2 +- .gitlab/common.yml | 2 +- .gitlab/ssi-package.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitlab/build-and-test-fast.yml b/.gitlab/build-and-test-fast.yml index 96c54963..7f39bc5e 100644 --- a/.gitlab/build-and-test-fast.yml +++ b/.gitlab/build-and-test-fast.yml @@ -40,7 +40,7 @@ lint: shellcheck: extends: .build-and-test-fast - image: $CI_REGISTRY/nginx_musl_toolchain + image: $CI_REGISTRY/nginx_musl_toolchain:rust-1.85 tags: ["arch:amd64"] script: - find bin/ test/ example/ .gitlab/ \( -type f -executable -not -name '*.py' \) -o \( -name '*.sh' -type f \) | xargs shellcheck --exclude SC1071,SC1091,SC2317 diff --git a/.gitlab/common.yml b/.gitlab/common.yml index 3bcc1a56..c7a6b910 100644 --- a/.gitlab/common.yml +++ b/.gitlab/common.yml @@ -15,7 +15,7 @@ variables: .build: extends: .git-config - image: $CI_REGISTRY/nginx_musl_toolchain + image: $CI_REGISTRY/nginx_musl_toolchain:rust-1.85 tags: ["arch:$ARCH"] variables: MAKE_JOB_COUNT: "8" diff --git a/.gitlab/ssi-package.yml b/.gitlab/ssi-package.yml index 61a4b811..a6e4b4d5 100644 --- a/.gitlab/ssi-package.yml +++ b/.gitlab/ssi-package.yml @@ -10,7 +10,7 @@ .ssi-assemble: extends: .git-config - image: registry.ddbuild.io/ci/nginx-datadog/nginx_musl_toolchain + image: registry.ddbuild.io/ci/nginx-datadog/nginx_musl_toolchain:rust-1.85 stage: build parallel: matrix: From 724848044cb545ee30dc3edd0a78665166f22575 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chojnacki?= Date: Fri, 20 Mar 2026 19:20:28 +0100 Subject: [PATCH 09/16] Pass sysroot/target CFLAGS to Rust cc crate for cross-compilation aws-lc-sys (transitive dep via libdd-library-config -> rustls) compiles C code during its build script. Without sysroot flags, the linker cannot find crtbeginS.o in the musl cross-compilation environment. --- deps/CMakeLists.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/deps/CMakeLists.txt b/deps/CMakeLists.txt index f2d8f81e..db61f38a 100644 --- a/deps/CMakeLists.txt +++ b/deps/CMakeLists.txt @@ -13,6 +13,15 @@ FetchContent_Declare( ) FetchContent_MakeAvailable(InjectBrowserSDK) +# Pass cross-compilation sysroot/target flags to Rust cc crate builds +# (e.g. aws-lc-sys) that invoke the C compiler via CFLAGS. +if(CMAKE_SYSROOT AND CMAKE_C_COMPILER_TARGET AND COMMAND corrosion_set_env_vars) + string(REPLACE "-" "_" _rust_env_target "${Rust_CARGO_TARGET}") + corrosion_set_env_vars(inject_browser_sdk_ffi + "CFLAGS_${_rust_env_target}=--sysroot=${CMAKE_SYSROOT} --target=${CMAKE_C_COMPILER_TARGET}" + ) +endif() + if(NOT TARGET inject_browser_sdk) add_library(inject_browser_sdk ALIAS inject_browser_sdk_ffi) endif() From 35155f5637656df97021d1bec55f445c3792400a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chojnacki?= Date: Fri, 20 Mar 2026 19:46:28 +0100 Subject: [PATCH 10/16] Fix CFLAGS env var: use explicit musl target names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rust_CARGO_TARGET is empty at the point corrosion_set_env_vars runs. Use hardcoded x86_64/aarch64 target names instead — only one will match the actual cargo build target, the other is harmlessly ignored. --- deps/CMakeLists.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/deps/CMakeLists.txt b/deps/CMakeLists.txt index db61f38a..f0fc51cf 100644 --- a/deps/CMakeLists.txt +++ b/deps/CMakeLists.txt @@ -16,9 +16,10 @@ FetchContent_MakeAvailable(InjectBrowserSDK) # Pass cross-compilation sysroot/target flags to Rust cc crate builds # (e.g. aws-lc-sys) that invoke the C compiler via CFLAGS. if(CMAKE_SYSROOT AND CMAKE_C_COMPILER_TARGET AND COMMAND corrosion_set_env_vars) - string(REPLACE "-" "_" _rust_env_target "${Rust_CARGO_TARGET}") + set(_cross_cflags "--sysroot=${CMAKE_SYSROOT} --target=${CMAKE_C_COMPILER_TARGET}") corrosion_set_env_vars(inject_browser_sdk_ffi - "CFLAGS_${_rust_env_target}=--sysroot=${CMAKE_SYSROOT} --target=${CMAKE_C_COMPILER_TARGET}" + "CFLAGS_x86_64_unknown_linux_musl=${_cross_cflags}" + "CFLAGS_aarch64_unknown_linux_musl=${_cross_cflags}" ) endif() From dc0e2226c00a911b8f5f298b77beea37334bbfbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chojnacki?= Date: Fri, 20 Mar 2026 19:57:30 +0100 Subject: [PATCH 11/16] Add -fuse-ld=lld -rtlib=compiler-rt to cross-compilation CFLAGS aws-lc-sys build script compile+links test binaries via clang. Without these flags, clang invokes system GNU ld which can't find crtbeginS.o and libgcc in the musl sysroot. Using lld and compiler-rt matches the rest of the toolchain setup. --- deps/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/deps/CMakeLists.txt b/deps/CMakeLists.txt index f0fc51cf..680c1dcf 100644 --- a/deps/CMakeLists.txt +++ b/deps/CMakeLists.txt @@ -16,10 +16,10 @@ FetchContent_MakeAvailable(InjectBrowserSDK) # Pass cross-compilation sysroot/target flags to Rust cc crate builds # (e.g. aws-lc-sys) that invoke the C compiler via CFLAGS. if(CMAKE_SYSROOT AND CMAKE_C_COMPILER_TARGET AND COMMAND corrosion_set_env_vars) - set(_cross_cflags "--sysroot=${CMAKE_SYSROOT} --target=${CMAKE_C_COMPILER_TARGET}") + set(_cross_flags "--sysroot=${CMAKE_SYSROOT} --target=${CMAKE_C_COMPILER_TARGET} -fuse-ld=lld -rtlib=compiler-rt") corrosion_set_env_vars(inject_browser_sdk_ffi - "CFLAGS_x86_64_unknown_linux_musl=${_cross_cflags}" - "CFLAGS_aarch64_unknown_linux_musl=${_cross_cflags}" + "CFLAGS_x86_64_unknown_linux_musl=${_cross_flags}" + "CFLAGS_aarch64_unknown_linux_musl=${_cross_flags}" ) endif() From ed785f3377716de4c99a84660372486494939c72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chojnacki?= Date: Fri, 20 Mar 2026 20:48:34 +0100 Subject: [PATCH 12/16] Update RUM tests to use stable config files instead of env vars test_env_only_config and test_partial_env_config now write application_monitoring.yaml into the container instead of setting DD_RUM_* env vars, matching the new stable config integration. --- test/cases/rum/test_injection.py | 106 ++++++++++++++++++++----------- 1 file changed, 70 insertions(+), 36 deletions(-) diff --git a/test/cases/rum/test_injection.py b/test/cases/rum/test_injection.py index 2280115e..2b52e057 100644 --- a/test/cases/rum/test_injection.py +++ b/test/cases/rum/test_injection.py @@ -373,22 +373,51 @@ def test_injection_disabled(self): self.assertIsNone(headers.get("x-datadog-rum-injected")) self.assertNotIn("datadog-rum.js", body) + def _write_stable_config(self, config_vars): + """Write an application_monitoring.yaml into the nginx container + at the stable config path used by snippet_create_from_stable_config.""" + import subprocess + from ..orchestration import docker_compose_command, child_env + yaml_lines = ["apm_configuration_default:"] + for key, value in config_vars.items(): + yaml_lines.append(f" {key}: {value}") + yaml_content = "\n".join(yaml_lines) + "\n" + + config_path = "/etc/datadog-agent/application_monitoring.yaml" + command = docker_compose_command( + "exec", "-T", "--", "nginx", "/bin/sh", "-c", + f"mkdir -p /etc/datadog-agent && cat >'{config_path}'") + subprocess.run( + command, input=yaml_content, encoding="utf8", + env=child_env(), check=True, + capture_output=True) + + def _cleanup_stable_config(self): + """Remove the stable config file from the nginx container.""" + import subprocess + from ..orchestration import docker_compose_command, child_env + command = docker_compose_command( + "exec", "-T", "--", "nginx", + "rm", "-f", "/etc/datadog-agent/application_monitoring.yaml") + subprocess.run( + command, env=child_env(), check=True, + capture_output=True) + def test_env_only_config(self): """ - Verify RUM injection works when configuration comes entirely from - DD_RUM_* environment variables, with no datadog_rum_config directive - in the nginx config. + Verify RUM injection works when configuration comes from the + stable config file (application_monitoring.yaml), with no + datadog_rum_config directive in the nginx config. """ conf_path = Path(__file__).parent / "conf" / "rum_env_only.conf" nginx_conf = conf_path.read_text() - env = { + stable_config = { "DD_RUM_APPLICATION_ID": "", "DD_RUM_CLIENT_TOKEN": "", "DD_RUM_SITE": "datadoghq.com", "DD_RUM_SERVICE": "env-only-service", "DD_RUM_ENVIRONMENT": "env-test", - "DD_RUM_MAJOR_VERSION": "3.0.0", "DD_RUM_SESSION_SAMPLE_RATE": "100", "DD_RUM_SESSION_REPLAY_SAMPLE_RATE": "50", "DD_RUM_TRACK_RESOURCES": "true", @@ -396,29 +425,31 @@ def test_env_only_config(self): "DD_RUM_TRACK_USER_INTERACTIONS": "true", } - with self.orch.custom_nginx(nginx_conf, - extra_env=env, - healthcheck_port=80) as nginx: - status, headers, body = self.orch.send_nginx_http_request("/") - self.assertEqual(200, status) - self.assertInjection(headers, body) - - self.assertIn('"applicationId":""', body) - self.assertIn('"clientToken":""', body) - self.assertIn('"service":"env-only-service"', body) - self.assertIn('"env":"env-test"', body) - self.assertIn('"version":"3.0.0"', body) + self._write_stable_config(stable_config) + try: + with self.orch.custom_nginx(nginx_conf, + healthcheck_port=80) as nginx: + status, headers, body = self.orch.send_nginx_http_request("/") + self.assertEqual(200, status) + self.assertInjection(headers, body) + + self.assertIn('"applicationId":""', body) + self.assertIn('"clientToken":""', body) + self.assertIn('"service":"env-only-service"', body) + self.assertIn('"env":"env-test"', body) + finally: + self._cleanup_stable_config() def test_partial_env_config(self): """ - Verify that nginx config fields override corresponding DD_RUM_* env - vars (per-field merging). The datadog_rum_config block sets service - and env; the remaining fields come from env vars. + Verify that nginx config fields override corresponding stable config + values (per-field merging). The datadog_rum_config block sets service + and env; the remaining fields come from stable config. """ conf_path = Path(__file__).parent / "conf" / "rum_partial_env.conf" nginx_conf = conf_path.read_text() - env = { + stable_config = { "DD_RUM_APPLICATION_ID": "", "DD_RUM_CLIENT_TOKEN": "", "DD_RUM_SITE": "datadoghq.eu", @@ -431,21 +462,24 @@ def test_partial_env_config(self): "DD_RUM_TRACK_USER_INTERACTIONS": "true", } - with self.orch.custom_nginx(nginx_conf, - extra_env=env, - healthcheck_port=80) as nginx: - status, headers, body = self.orch.send_nginx_http_request("/") - self.assertEqual(200, status) - self.assertInjection(headers, body) - - # nginx config values take precedence - self.assertIn('"service":"nginx-partial-env"', body) - self.assertIn('"env":"staging"', body) - - # env var values used for fields not in nginx config - self.assertIn('"applicationId":""', body) - self.assertIn('"clientToken":""', body) - self.assertIn('"site":"datadoghq.eu"', body) + self._write_stable_config(stable_config) + try: + with self.orch.custom_nginx(nginx_conf, + healthcheck_port=80) as nginx: + status, headers, body = self.orch.send_nginx_http_request("/") + self.assertEqual(200, status) + self.assertInjection(headers, body) + + # nginx config values take precedence + self.assertIn('"service":"nginx-partial-env"', body) + self.assertIn('"env":"staging"', body) + + # stable config values used for fields not in nginx config + self.assertIn('"applicationId":""', body) + self.assertIn('"clientToken":""', body) + self.assertIn('"site":"datadoghq.eu"', body) + finally: + self._cleanup_stable_config() def test_nginx_config_takes_full_precedence(self): """ From 7d9f80a46c35ddf96c3890c59ba68bdeb4d8d432 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chojnacki?= Date: Fri, 20 Mar 2026 21:06:37 +0100 Subject: [PATCH 13/16] Update remaining RUM tests to use stable config files test_env_remote_configuration_id, test_env_disabled_overrides_env_config, and test_env_disabled_location_override now use application_monitoring.yaml instead of DD_RUM_* env vars. DD_RUM_ENABLED still uses env var since it controls the enable/disable flag, not the config source. --- test/cases/rum/test_injection.py | 73 ++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 31 deletions(-) diff --git a/test/cases/rum/test_injection.py b/test/cases/rum/test_injection.py index 2b52e057..09e3fd3d 100644 --- a/test/cases/rum/test_injection.py +++ b/test/cases/rum/test_injection.py @@ -508,7 +508,7 @@ def test_env_remote_configuration_id(self): conf_path = Path(__file__).parent / "conf" / "rum_env_only.conf" nginx_conf = conf_path.read_text() - env = { + stable_config = { "DD_RUM_APPLICATION_ID": "", "DD_RUM_CLIENT_TOKEN": "", "DD_RUM_SITE": "datadoghq.com", @@ -516,64 +516,75 @@ def test_env_remote_configuration_id(self): "DD_RUM_REMOTE_CONFIGURATION_ID": "abc-123-remote-cfg", } - with self.orch.custom_nginx(nginx_conf, - extra_env=env, - healthcheck_port=80) as nginx: - status, headers, body = self.orch.send_nginx_http_request("/") - self.assertEqual(200, status) - self.assertInjection(headers, body) + self._write_stable_config(stable_config) + try: + with self.orch.custom_nginx(nginx_conf, + healthcheck_port=80) as nginx: + status, headers, body = self.orch.send_nginx_http_request("/") + self.assertEqual(200, status) + self.assertInjection(headers, body) - self.assertIn('"remoteConfigurationId":"abc-123-remote-cfg"', body) + self.assertIn('"remoteConfigurationId":"abc-123-remote-cfg"', body) + finally: + self._cleanup_stable_config() def test_env_disabled_overrides_env_config(self): """ - Verify DD_RUM_ENABLED=false disables RUM even when DD_RUM_* config - env vars are present. + Verify DD_RUM_ENABLED=false disables RUM even when stable config + provides a complete RUM configuration. """ conf_path = Path(__file__).parent / "conf" / "rum_env_only.conf" nginx_conf = conf_path.read_text() - env = { - "DD_RUM_ENABLED": "false", + stable_config = { "DD_RUM_APPLICATION_ID": "", "DD_RUM_CLIENT_TOKEN": "", "DD_RUM_SITE": "datadoghq.com", "DD_RUM_SERVICE": "should-not-inject", } - with self.orch.custom_nginx(nginx_conf, - extra_env=env, - healthcheck_port=80) as nginx: - status, headers, body = self.orch.send_nginx_http_request("/") - self.assertEqual(200, status) - headers = self.make_dict_headers(headers) - self.assertIsNone(headers.get("x-datadog-rum-injected")) - self.assertNotIn("datadog-rum.js", body) + env = {"DD_RUM_ENABLED": "false"} + + self._write_stable_config(stable_config) + try: + with self.orch.custom_nginx(nginx_conf, + extra_env=env, + healthcheck_port=80) as nginx: + status, headers, body = self.orch.send_nginx_http_request("/") + self.assertEqual(200, status) + headers = self.make_dict_headers(headers) + self.assertIsNone(headers.get("x-datadog-rum-injected")) + self.assertNotIn("datadog-rum.js", body) + finally: + self._cleanup_stable_config() def test_env_disabled_location_override(self): """ Verify that datadog_rum off in a location still disables injection - even when env vars provide a complete RUM config. + even when stable config provides a complete RUM configuration. """ conf_path = Path(__file__).parent / "conf" / "rum_env_only.conf" nginx_conf = conf_path.read_text() - env = { + stable_config = { "DD_RUM_APPLICATION_ID": "", "DD_RUM_CLIENT_TOKEN": "", "DD_RUM_SITE": "datadoghq.com", "DD_RUM_SERVICE": "env-service", } - with self.orch.custom_nginx(nginx_conf, - extra_env=env, - healthcheck_port=80) as nginx: - status, headers, body = self.orch.send_nginx_http_request( - "/disable-rum") - self.assertEqual(200, status) - headers = self.make_dict_headers(headers) - self.assertIsNone(headers.get("x-datadog-rum-injected")) - self.assertNotIn("datadog-rum.js", body) + self._write_stable_config(stable_config) + try: + with self.orch.custom_nginx(nginx_conf, + healthcheck_port=80) as nginx: + status, headers, body = self.orch.send_nginx_http_request( + "/disable-rum") + self.assertEqual(200, status) + headers = self.make_dict_headers(headers) + self.assertIsNone(headers.get("x-datadog-rum-injected")) + self.assertNotIn("datadog-rum.js", body) + finally: + self._cleanup_stable_config() def test_skip_injection_when_already_injected(self): """ From dfa6597fa1252c192f2ed7c0523f75173e45da13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chojnacki?= Date: Fri, 20 Mar 2026 21:32:33 +0100 Subject: [PATCH 14/16] Fix Python formatting in RUM test helpers --- test/cases/rum/test_injection.py | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/test/cases/rum/test_injection.py b/test/cases/rum/test_injection.py index 09e3fd3d..4026f98c 100644 --- a/test/cases/rum/test_injection.py +++ b/test/cases/rum/test_injection.py @@ -387,21 +387,24 @@ def _write_stable_config(self, config_vars): command = docker_compose_command( "exec", "-T", "--", "nginx", "/bin/sh", "-c", f"mkdir -p /etc/datadog-agent && cat >'{config_path}'") - subprocess.run( - command, input=yaml_content, encoding="utf8", - env=child_env(), check=True, - capture_output=True) + subprocess.run(command, + input=yaml_content, + encoding="utf8", + env=child_env(), + check=True, + capture_output=True) def _cleanup_stable_config(self): """Remove the stable config file from the nginx container.""" import subprocess from ..orchestration import docker_compose_command, child_env command = docker_compose_command( - "exec", "-T", "--", "nginx", - "rm", "-f", "/etc/datadog-agent/application_monitoring.yaml") - subprocess.run( - command, env=child_env(), check=True, - capture_output=True) + "exec", "-T", "--", "nginx", "rm", "-f", + "/etc/datadog-agent/application_monitoring.yaml") + subprocess.run(command, + env=child_env(), + check=True, + capture_output=True) def test_env_only_config(self): """ @@ -524,7 +527,8 @@ def test_env_remote_configuration_id(self): self.assertEqual(200, status) self.assertInjection(headers, body) - self.assertIn('"remoteConfigurationId":"abc-123-remote-cfg"', body) + self.assertIn( + '"remoteConfigurationId":"abc-123-remote-cfg"', body) finally: self._cleanup_stable_config() From 7953e4519bab355f66445629468d72086835df1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chojnacki?= Date: Fri, 20 Mar 2026 21:37:32 +0100 Subject: [PATCH 15/16] Fix assertIn line wrapping per formatter --- test/cases/rum/test_injection.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/cases/rum/test_injection.py b/test/cases/rum/test_injection.py index 4026f98c..39ad2616 100644 --- a/test/cases/rum/test_injection.py +++ b/test/cases/rum/test_injection.py @@ -527,8 +527,8 @@ def test_env_remote_configuration_id(self): self.assertEqual(200, status) self.assertInjection(headers, body) - self.assertIn( - '"remoteConfigurationId":"abc-123-remote-cfg"', body) + self.assertIn('"remoteConfigurationId":"abc-123-remote-cfg"', + body) finally: self._cleanup_stable_config() From 352baeff27bd9d0bba7850bb39d4af707a05f10a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chojnacki?= Date: Fri, 20 Mar 2026 22:18:36 +0100 Subject: [PATCH 16/16] Update inject-browser-sdk to f509450 Adds DD_RUM_REMOTE_CONFIGURATION_ID support in configuration_from_getter so remoteConfigurationId appears in snippets created via stable config. --- deps/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/CMakeLists.txt b/deps/CMakeLists.txt index 680c1dcf..038cd9d8 100644 --- a/deps/CMakeLists.txt +++ b/deps/CMakeLists.txt @@ -1,6 +1,6 @@ include(FetchContent) -set(INJECT_BROWSER_SDK_GIT_REF "587b071" CACHE STRING +set(INJECT_BROWSER_SDK_GIT_REF "f509450" CACHE STRING "Git tag/branch for inject-browser-sdk") set(INJECT_BROWSER_SDK_NO_DEFAULT_FEATURES OFF CACHE BOOL