Skip to content

Commit a32e4f5

Browse files
committed
Merge branch 'master' of github.com:DataDog/dd-trace-php into bob/libdd-update
* 'master' of github.com:DataDog/dd-trace-php: feat(sidecar): add thread mode as fallback connection for restricted environments (#3573) Migrate deprecated GitLab runner tags (#3715) Adds process tags to remote config payload (#3658) perf(config): cache sys getenv (#3670) Fixes the tag name for process tags (#3709) Fix debugger ephemerals handling (#3685) Fix #3651: Prevent crash during shutdown in Frankenphp (#3662) Add dynamic instrumentation and exception replay to startup logging (#3667) chore: bump bytes crate from 1.9.0 to 1.11.1 to address CVE-2026-25541 (#3669) Merge pull request #3701 from DataDog/brian.marks/add-ksr-tag ci: fix Windows job flakiness caused by dirty workspace (#3694) Fixup CI owner association (#3704) Add Rust rewrite of the AppSec helper alongside the C++ implementation Remove debug instruction Fix script order debug Fix exploration logic chore(ci): add final_status property on junit XML [APMSP-2610] Fix DD_TRACE_SYMFONY_HTTP_ROUTE=false Optimize Symfony http.route caching with path map approach
2 parents fc3c1ee + d442722 commit a32e4f5

File tree

200 files changed

+16332
-870
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

200 files changed

+16332
-870
lines changed

.gitlab-ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ appsec-trigger:
5757
strategy: depend
5858
variables:
5959
PARENT_PIPELINE_ID: $CI_PIPELINE_ID
60-
GIT_SUBMODULE_PATHS: libdatadog appsec/third_party/cpp-base64 appsec/third_party/libddwaf appsec/third_party/msgpack-c
60+
GIT_SUBMODULE_PATHS: libdatadog appsec/third_party/cpp-base64 appsec/third_party/libddwaf appsec/third_party/libddwaf-rust appsec/third_party/msgpack-c
6161

6262
profiler-trigger:
6363
stage: tests
@@ -92,6 +92,6 @@ package-trigger:
9292
strategy: depend
9393
variables:
9494
PARENT_PIPELINE_ID: $CI_PIPELINE_ID
95-
GIT_SUBMODULE_PATHS: libdatadog appsec/third_party/cpp-base64 appsec/third_party/libddwaf appsec/third_party/msgpack-c
95+
GIT_SUBMODULE_PATHS: libdatadog appsec/third_party/cpp-base64 appsec/third_party/libddwaf appsec/third_party/libddwaf-rust appsec/third_party/msgpack-c
9696
NIGHTLY_BUILD: $NIGHTLY_BUILD
9797
RELIABILITY_ENV_BRANCH: $RELIABILITY_ENV_BRANCH

.gitlab/add_final_status.xsl

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
3+
4+
<!-- Identity transform: copy everything as-is by default -->
5+
<xsl:template match="@*|node()">
6+
<xsl:copy>
7+
<xsl:apply-templates select="@*|node()"/>
8+
</xsl:copy>
9+
</xsl:template>
10+
11+
<!-- For testcase elements missing dd_tags[test.final_status] inside their properties block -->
12+
<xsl:template match="testcase[not(properties/property[@name='dd_tags[test.final_status]'])]">
13+
<xsl:copy>
14+
<xsl:apply-templates select="@*"/>
15+
<xsl:variable name="status">
16+
<xsl:choose>
17+
<xsl:when test="failure or error">fail</xsl:when>
18+
<xsl:when test="skipped">skip</xsl:when>
19+
<xsl:otherwise>pass</xsl:otherwise>
20+
</xsl:choose>
21+
</xsl:variable>
22+
<xsl:choose>
23+
<xsl:when test="properties">
24+
<!-- Inject into existing properties block, preserving child order -->
25+
<xsl:for-each select="node()">
26+
<xsl:choose>
27+
<xsl:when test="self::properties">
28+
<properties>
29+
<xsl:apply-templates select="@*|node()"/>
30+
<property name="dd_tags[test.final_status]" value="{$status}"/>
31+
</properties>
32+
</xsl:when>
33+
<xsl:otherwise>
34+
<xsl:apply-templates select="."/>
35+
</xsl:otherwise>
36+
</xsl:choose>
37+
</xsl:for-each>
38+
</xsl:when>
39+
<xsl:otherwise>
40+
<!-- No properties block: create one before other children -->
41+
<properties>
42+
<property name="dd_tags[test.final_status]" value="{$status}"/>
43+
</properties>
44+
<xsl:apply-templates select="node()"/>
45+
</xsl:otherwise>
46+
</xsl:choose>
47+
</xsl:copy>
48+
</xsl:template>
49+
50+
</xsl:stylesheet>
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#!/usr/bin/env bash
2+
set -e -o pipefail
3+
4+
MAKE_JOBS=${MAKE_JOBS:-$(nproc)}
5+
6+
mkdir -p appsec_$(uname -m)
7+
8+
git config --global --add safe.directory '*'
9+
10+
cd appsec/helper-rust
11+
12+
export CARGO_TARGET_DIR=/tmp/cargo-target
13+
RUST_TARGET=$(uname -m)-unknown-linux-musl
14+
15+
# Build using nightly toolchain with unstable features
16+
# -Z build-std: Rebuild std library for musl
17+
# -Z build-std-features=llvm-libunwind: Use LLVM libunwind instead of libgcc_s
18+
cargo +nightly-"$RUST_TARGET" build \
19+
--release \
20+
-Zhost-config \
21+
-Ztarget-applies-to-host \
22+
--target "$RUST_TARGET"
23+
24+
# Remove musl libc dependency using patchelf (makes binary work on both musl and glibc)
25+
BINARY_PATH="/tmp/cargo-target/$RUST_TARGET/release/libddappsec_helper_rust.so"
26+
ARCH=$(uname -m)
27+
if [ "$ARCH" = "x86_64" ]; then
28+
patchelf --remove-needed libc.musl-x86_64.so.1 "$BINARY_PATH" 2>/dev/null || true
29+
elif [ "$ARCH" = "aarch64" ]; then
30+
patchelf --remove-needed libc.musl-aarch64.so.1 "$BINARY_PATH" 2>/dev/null || true
31+
fi
32+
33+
# Copy to output
34+
cp -v "$BINARY_PATH" "../../appsec_$(uname -m)/libddappsec-helper-rust.so"
35+
36+
# Run tests
37+
cargo +nightly-"$RUST_TARGET" test \
38+
--release \
39+
-Zhost-config \
40+
-Ztarget-applies-to-host \
41+
--target "$RUST_TARGET"

.gitlab/generate-appsec.php

Lines changed: 203 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,16 +94,52 @@
9494
-DENABLE_ASAN=$ASAN_FLAG"
9595
- ASAN_OPTIONS=malloc_context_size=0 make -j 4 xtest
9696

97-
"appsec integration tests":
97+
.appsec_integration_tests:
9898
stage: test
9999
image: 486234852809.dkr.ecr.us-east-1.amazonaws.com/docker:24.0.4-gbi-focal # TODO: use a proper docker image with java pre-installed?
100100
tags: [ "docker-in-docker:amd64" ]
101101
variables:
102102
KUBERNETES_CPU_REQUEST: 8
103103
KUBERNETES_MEMORY_REQUEST: 24Gi
104104
KUBERNETES_MEMORY_LIMIT: 30Gi
105+
DOCKER_LOOPBACK_SIZE: 30G
105106
ARCH: amd64
107+
HELPER_RUST_FLAG: ""
106108
GRADLE_USER_HOME: "$CI_PROJECT_DIR/.gradle-home"
109+
before_script:
110+
<?php echo $ecrLoginSnippet, "\n"; ?>
111+
<?php dockerhub_login() ?>
112+
script:
113+
- apt update && apt install -y openjdk-17-jre
114+
- find "$CI_PROJECT_DIR"/appsec/tests/integration/build || true
115+
- |
116+
cd appsec/tests/integration
117+
CACHE_PATH=build/php-appsec-volume-caches-${ARCH}.tar.gz
118+
if [ -f "$CACHE_PATH" ]; then
119+
echo "Loading cache from $CACHE_PATH"
120+
TERM=dumb ./gradlew loadCaches --info
121+
fi
122+
123+
TERM=dumb ./gradlew $targets --info -Pbuildscan --scan $HELPER_RUST_FLAG
124+
TERM=dumb ./gradlew saveCaches --info
125+
after_script:
126+
- mkdir -p "${CI_PROJECT_DIR}/artifacts"
127+
- find appsec/tests/integration/build/test-results -name "*.xml" -exec cp --parents '{}' "${CI_PROJECT_DIR}/artifacts/" \;
128+
- .gitlab/upload-junit-to-datadog.sh "test.source.file:appsec/"
129+
artifacts:
130+
reports:
131+
junit: "artifacts/**/test-results/**/TEST-*.xml"
132+
paths:
133+
- "artifacts/"
134+
when: "always"
135+
cache:
136+
- key: "appsec int test cache"
137+
paths:
138+
- appsec/tests/integration/build/*.tar.gz
139+
- .gradle-home/wrapper/dists/
140+
141+
"appsec integration tests":
142+
extends: .appsec_integration_tests
107143
parallel:
108144
matrix:
109145
- targets:
@@ -129,33 +165,194 @@
129165
- test8.4-release-zts
130166
- test8.5-release
131167
- test8.5-release-zts
168+
- test8.5-release-musl
169+
170+
"appsec integration tests (helper-rust)":
171+
extends: .appsec_integration_tests
172+
variables:
173+
HELPER_RUST_FLAG: "-PuseHelperRust"
174+
parallel:
175+
matrix:
176+
- targets:
177+
- test7.4-release
178+
- test8.1-release
179+
- test8.3-debug
180+
- test8.4-release-zts
181+
- test8.5-release-musl
182+
183+
"helper-rust build and test":
184+
stage: test
185+
image: 486234852809.dkr.ecr.us-east-1.amazonaws.com/docker:24.0.4-gbi-focal
186+
tags: [ "docker-in-docker:amd64" ]
187+
interruptible: true
188+
rules:
189+
- if: $CI_COMMIT_BRANCH == "master"
190+
interruptible: false
191+
- when: on_success
192+
variables:
193+
KUBERNETES_CPU_REQUEST: 4
194+
KUBERNETES_MEMORY_REQUEST: 8Gi
195+
KUBERNETES_MEMORY_LIMIT: 10Gi
196+
ARCH: amd64
132197
before_script:
133198
<?php echo $ecrLoginSnippet, "\n"; ?>
134199
<?php dockerhub_login() ?>
135200
script:
136201
- apt update && apt install -y openjdk-17-jre
137-
- find "$CI_PROJECT_DIR"/appsec/tests/integration/build || true
138202
- |
139203
cd appsec/tests/integration
140204
CACHE_PATH=build/php-appsec-volume-caches-${ARCH}.tar.gz
141205
if [ -f "$CACHE_PATH" ]; then
142206
echo "Loading cache from $CACHE_PATH"
143207
TERM=dumb ./gradlew loadCaches --info
144208
fi
209+
# Build and test helper-rust (includes formatting check and cargo test)
210+
TERM=dumb ./gradlew testHelperRust --info -Pbuildscan --scan
211+
TERM=dumb ./gradlew saveCaches --info
212+
cache:
213+
- key: "appsec int test cache"
214+
paths:
215+
- appsec/tests/integration/build/*.tar.gz
216+
- .gradle-home/wrapper/dists/
217+
218+
"helper-rust code coverage":
219+
stage: test
220+
image: 486234852809.dkr.ecr.us-east-1.amazonaws.com/docker:24.0.4-gbi-focal
221+
tags: [ "docker-in-docker:amd64" ]
222+
interruptible: true
223+
rules:
224+
- if: $CI_COMMIT_BRANCH == "master"
225+
interruptible: false
226+
- when: on_success
227+
variables:
228+
KUBERNETES_CPU_REQUEST: 4
229+
KUBERNETES_MEMORY_REQUEST: 8Gi
230+
KUBERNETES_MEMORY_LIMIT: 10Gi
231+
ARCH: amd64
232+
before_script:
233+
<?php echo $ecrLoginSnippet, "\n"; ?>
234+
<?php dockerhub_login() ?>
235+
script:
236+
- apt update && apt install -y openjdk-17-jre
237+
- |
238+
echo "Installing codecov CLI"
239+
curl https://keybase.io/codecovsecurity/pgp_keys.asc | gpg --no-default-keyring --keyring trustedkeys.gpg --import
240+
CODECOV_VERSION=0.6.1
241+
curl -Os https://uploader.codecov.io/v${CODECOV_VERSION}/linux/codecov
242+
curl -Os https://uploader.codecov.io/v${CODECOV_VERSION}/linux/codecov.SHA256SUM
243+
curl -Os https://uploader.codecov.io/v${CODECOV_VERSION}/linux/codecov.SHA256SUM.sig
244+
gpgv codecov.SHA256SUM.sig codecov.SHA256SUM
245+
shasum -a 256 -c codecov.SHA256SUM
246+
rm codecov.SHA256SUM.sig codecov.SHA256SUM
247+
chmod +x codecov
248+
mv codecov /usr/local/bin/codecov
249+
- |
250+
echo "Installing vault for codecov token"
251+
curl -o vault.zip https://releases.hashicorp.com/vault/1.20.0/vault_1.20.0_linux_amd64.zip
252+
unzip vault.zip
253+
mv vault /usr/local/bin/vault
254+
rm vault.zip
255+
- |
256+
cd appsec/tests/integration
257+
CACHE_PATH=build/php-appsec-volume-caches-${ARCH}.tar.gz
258+
if [ -f "$CACHE_PATH" ]; then
259+
echo "Loading cache from $CACHE_PATH"
260+
TERM=dumb ./gradlew loadCaches --info
261+
fi
262+
# Run unit tests with coverage instrumentation
263+
TERM=dumb ./gradlew coverageHelperRust --info -Pbuildscan --scan
264+
TERM=dumb ./gradlew saveCaches --info
265+
- |
266+
echo "Extracting coverage data from Docker volume"
267+
mkdir -p "$CI_PROJECT_DIR"/appsec/helper-rust
268+
docker run --rm -v php-helper-rust-coverage:/vol alpine cat /vol/coverage-unit.lcov > "$CI_PROJECT_DIR"/appsec/helper-rust/coverage-unit.lcov
269+
- |
270+
echo "Uploading helper-rust unit test coverage to codecov"
271+
cd "$CI_PROJECT_DIR"
272+
CODECOV_TOKEN=$(vault kv get --format=json kv/k8s/gitlab-runner/dd-trace-php/codecov | jq -r .data.data.token)
273+
codecov -t "$CODECOV_TOKEN" -n helper-rust-unit -F helper-rust-unit -v -f appsec/helper-rust/coverage-unit.lcov
274+
artifacts:
275+
paths:
276+
- appsec/helper-rust/coverage-unit.lcov
277+
when: always
278+
cache:
279+
- key: "appsec int test cache"
280+
paths:
281+
- appsec/tests/integration/build/*.tar.gz
282+
- .gradle-home/wrapper/dists/
145283

146-
TERM=dumb ./gradlew $targets --info -Pbuildscan --scan
284+
"helper-rust integration coverage":
285+
stage: test
286+
image: 486234852809.dkr.ecr.us-east-1.amazonaws.com/docker:24.0.4-gbi-focal
287+
tags: [ "docker-in-docker:amd64" ]
288+
interruptible: true
289+
rules:
290+
- if: $CI_COMMIT_BRANCH == "master"
291+
interruptible: false
292+
- when: on_success
293+
variables:
294+
KUBERNETES_CPU_REQUEST: 8
295+
KUBERNETES_MEMORY_REQUEST: 24Gi
296+
KUBERNETES_MEMORY_LIMIT: 30Gi
297+
ARCH: amd64
298+
before_script:
299+
<?php echo $ecrLoginSnippet, "\n"; ?>
300+
<?php dockerhub_login() ?>
301+
script:
302+
- apt update && apt install -y openjdk-17-jre
303+
- |
304+
echo "Installing codecov CLI"
305+
curl https://keybase.io/codecovsecurity/pgp_keys.asc | gpg --no-default-keyring --keyring trustedkeys.gpg --import
306+
CODECOV_VERSION=0.6.1
307+
curl -Os https://uploader.codecov.io/v${CODECOV_VERSION}/linux/codecov
308+
curl -Os https://uploader.codecov.io/v${CODECOV_VERSION}/linux/codecov.SHA256SUM
309+
curl -Os https://uploader.codecov.io/v${CODECOV_VERSION}/linux/codecov.SHA256SUM.sig
310+
gpgv codecov.SHA256SUM.sig codecov.SHA256SUM
311+
shasum -a 256 -c codecov.SHA256SUM
312+
rm codecov.SHA256SUM.sig codecov.SHA256SUM
313+
chmod +x codecov
314+
mv codecov /usr/local/bin/codecov
315+
- |
316+
echo "Installing vault for codecov token"
317+
curl -o vault.zip https://releases.hashicorp.com/vault/1.20.0/vault_1.20.0_linux_amd64.zip
318+
unzip vault.zip
319+
mv vault /usr/local/bin/vault
320+
rm vault.zip
321+
- |
322+
cd appsec/tests/integration
323+
CACHE_PATH=build/php-appsec-volume-caches-${ARCH}.tar.gz
324+
if [ -f "$CACHE_PATH" ]; then
325+
echo "Loading cache from $CACHE_PATH"
326+
TERM=dumb ./gradlew loadCaches --info
327+
fi
328+
# Build helper-rust with coverage instrumentation
329+
TERM=dumb ./gradlew buildHelperRustWithCoverage --info -Pbuildscan --scan
330+
# Run integration tests with coverage-instrumented binary
331+
TERM=dumb ./gradlew test8.3-debug --info -Pbuildscan --scan -PuseHelperRustCoverage
332+
# Generate coverage report from profraw files
333+
TERM=dumb ./gradlew generateHelperRustIntegrationCoverage --info -Pbuildscan --scan
147334
TERM=dumb ./gradlew saveCaches --info
335+
- |
336+
echo "Extracting coverage data from Docker volume"
337+
mkdir -p "$CI_PROJECT_DIR"/appsec/helper-rust
338+
docker run --rm -v php-helper-rust-coverage:/vol alpine cat /vol/coverage-integration.lcov > "$CI_PROJECT_DIR"/appsec/helper-rust/coverage-integration.lcov
339+
- |
340+
echo "Uploading helper-rust integration test coverage to codecov"
341+
cd "$CI_PROJECT_DIR"
342+
CODECOV_TOKEN=$(vault kv get --format=json kv/k8s/gitlab-runner/dd-trace-php/codecov | jq -r .data.data.token)
343+
codecov -t "$CODECOV_TOKEN" -n helper-rust-integration -F helper-rust-integration -v -f appsec/helper-rust/coverage-integration.lcov
148344
after_script:
149345
- mkdir -p "${CI_PROJECT_DIR}/artifacts"
150-
- find appsec/tests/integration/build/test-results -name "*.xml" -exec cp --parents '{}' "${CI_PROJECT_DIR}/artifacts/" \;
346+
- find appsec/tests/integration/build/test-results -name "*.xml" -exec cp --parents '{}' "${CI_PROJECT_DIR}/artifacts/" \; || true
151347
- cp -r appsec/tests/integration/build/test-logs "${CI_PROJECT_DIR}/artifacts/" 2>/dev/null || true
152-
- .gitlab/silent-upload-junit-to-datadog.sh "test.source.file:appsec"
348+
- .gitlab/silent-upload-junit-to-datadog.sh "test.source.file:appsec/"
153349
artifacts:
154350
reports:
155351
junit: "artifacts/**/test-results/**/TEST-*.xml"
156352
paths:
157353
- "artifacts/"
158-
when: "always"
354+
- appsec/helper-rust/coverage-integration.lcov
355+
when: always
159356
cache:
160357
- key: "appsec int test cache"
161358
paths:

0 commit comments

Comments
 (0)