@@ -105,41 +105,12 @@ jobs:
105105 - uses : Swatinem/rust-cache@v2
106106 with :
107107 key : ${{ matrix.target }}-smoke
108- - name : install Sury PHP 8.3
109- run : |
110- sudo apt-get update
111- sudo apt-get install -y --no-install-recommends \
112- curl ca-certificates gnupg lsb-release
113- curl -sSLo /tmp/sury.gpg https://packages.sury.org/php/apt.gpg
114- sudo install -m 644 /tmp/sury.gpg /usr/share/keyrings/sury.gpg
115- . /etc/os-release
116- echo "deb [signed-by=/usr/share/keyrings/sury.gpg] https://packages.sury.org/php/ ${VERSION_CODENAME} main" \
117- | sudo tee /etc/apt/sources.list.d/sury.list
118- sudo apt-get update
119- sudo apt-get install -y --no-install-recommends php8.3-cli
108+ - name : install PHP
109+ run : ./scripts/ci/install-php.sh
120110 - name : build
121111 run : cargo build --release --target ${{ matrix.target }}
122- - name : allow ptrace
123- run : |
124- echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope || true
125112 - name : smoke
126- run : |
127- cat > /tmp/spin.php <<'PHP'
128- <?php
129- class W { public function spin(): never { while (true) $this->a(); }
130- public function a(): void { $this->b(); }
131- public function b(): void { usleep(500); } }
132- (new W())->spin();
133- PHP
134- php8.3 /tmp/spin.php &
135- PID=$!
136- sleep 1
137- ./target/${{ matrix.target }}/release/pfp -p $PID -d 2 -H 99 -o /tmp/out.txt
138- kill $PID || true
139- wait || true
140- test "$(grep -c '^0 ' /tmp/out.txt)" -ge 100
141- grep -q 'W::a' /tmp/out.txt
142- grep -q 'W::b' /tmp/out.txt
113+ run : ./scripts/ci/smoke.sh ./target/${{ matrix.target }}/release/pfp
143114
144115 smoke-zts :
145116 name : smoke-zts (${{ matrix.target }})
@@ -167,38 +138,7 @@ jobs:
167138 - name : build
168139 run : cargo build --release --target ${{ matrix.target }}
169140 - name : smoke (ZTS)
170- # Run the ZTS PHP inside the official php:X.Y-zts image (the only
171- # convenient source of prebuilt ZTS binaries — Sury doesn't ship
172- # them). pfp runs inside the same container so we don't need to
173- # plumb pid namespaces between host and container.
174- run : |
175- cat > /tmp/spin.php <<'PHP'
176- <?php
177- class W { public function spin(): never { while (true) $this->a(); }
178- public function a(): void { $this->b(); }
179- public function b(): void { usleep(500); } }
180- (new W())->spin();
181- PHP
182- BIN=./target/${{ matrix.target }}/release/pfp
183- docker run -d --name php-zts \
184- --cap-add=SYS_PTRACE \
185- -v /tmp/spin.php:/spin.php:ro \
186- -v "$(realpath $BIN):/pfp:ro" \
187- ${{ matrix.php_image }} \
188- php /spin.php
189- sleep 1
190- docker exec php-zts php -i 2>/dev/null | grep -i 'thread safety' \
191- | grep -qi enabled
192- # php is the container's PID 1 — the docker-php-entrypoint execs
193- # the command — and the php:*-zts image ships no pgrep (no procps).
194- PHP_PID=1
195- docker exec php-zts /pfp -p "$PHP_PID" -d 2 -H 99 -o /tmp/out.txt
196- OUT=$(docker exec php-zts cat /tmp/out.txt)
197- docker rm -f php-zts
198- echo "$OUT" | head -20
199- test "$(echo "$OUT" | grep -c '^0 ')" -ge 100
200- echo "$OUT" | grep -q 'W::a'
201- echo "$OUT" | grep -q 'W::b'
141+ run : ./scripts/ci/smoke-zts.sh ./target/${{ matrix.target }}/release/pfp ${{ matrix.php_image }}
202142
203143 smoke-pyroscope :
204144 name : smoke-pyroscope
@@ -218,66 +158,9 @@ jobs:
218158 - uses : Swatinem/rust-cache@v2
219159 with :
220160 key : x86_64-unknown-linux-gnu-smoke-pyroscope
221- - name : install Sury PHP 8.3
222- run : |
223- sudo apt-get update
224- sudo apt-get install -y --no-install-recommends \
225- curl ca-certificates gnupg lsb-release
226- curl -sSLo /tmp/sury.gpg https://packages.sury.org/php/apt.gpg
227- sudo install -m 644 /tmp/sury.gpg /usr/share/keyrings/sury.gpg
228- . /etc/os-release
229- echo "deb [signed-by=/usr/share/keyrings/sury.gpg] https://packages.sury.org/php/ ${VERSION_CODENAME} main" \
230- | sudo tee /etc/apt/sources.list.d/sury.list
231- sudo apt-get update
232- sudo apt-get install -y --no-install-recommends php8.3-cli
161+ - name : install PHP
162+ run : ./scripts/ci/install-php.sh
233163 - name : build
234164 run : cargo build --release
235- - name : allow ptrace
236- run : echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope || true
237- - name : push profiles to pyroscope and query them back
238- run : |
239- set -euo pipefail
240- cat > /tmp/spin.php <<'PHP'
241- <?php
242- class W { public function spin(): never { while (true) $this->a(); }
243- public function a(): void { $this->b(); }
244- public function b(): void { usleep(500); } }
245- (new W())->spin();
246- PHP
247- php8.3 /tmp/spin.php &
248- PHP_PID=$!
249- sleep 1
250- # Run pfp continuously in sidecar/push mode; keep pushing while we poll.
251- RUST_LOG=pfp=debug ./target/release/pfp \
252- -p "$PHP_PID" --pyroscope-url http://localhost:4040 \
253- --pyroscope-app pfp-smoke --push-interval-secs 2 -H 99 \
254- > /tmp/pfp.log 2>&1 &
255- PFP_PID=$!
256-
257- # 1) Hard gate: pfp attached and pushed without errors. Pyroscope
258- # answers /ingest with 422 on a malformed pprof (which the sink
259- # logs as "push failed"), so a clean push proves the profile was
260- # parsed and accepted end-to-end by the server.
261- sleep 12
262- cat /tmp/pfp.log
263- grep -q 'attached pid=' /tmp/pfp.log
264- grep -q 'pushed profile to pyroscope' /tmp/pfp.log
265- ! grep -q 'push failed' /tmp/pfp.log
266-
267- # 2) Best-effort: confirm the profile is queryable with our PHP frames.
268- # Pyroscope's ingest->queryable lag is timing-dependent, so this is
269- # logged but does not gate the job (the push gate above is the
270- # deterministic e2e signal).
271- for i in $(seq 1 30); do
272- now=$(date +%s%3N); from=$((now - 600000))
273- body=$(printf '{"profile_typeID":"process_cpu:samples:count::","label_selector":"{service_name=\\"pfp-smoke\\"}","start":%s,"end":%s}' "$from" "$now")
274- names=$(curl -s -X POST \
275- http://localhost:4040/querier.v1.QuerierService/SelectMergeStacktraces \
276- -H 'Content-Type: application/json' -d "$body" \
277- | python3 -c 'import sys,json; print("\n".join(json.load(sys.stdin).get("flamegraph",{}).get("names",[])))' 2>/dev/null || true)
278- if echo "$names" | grep -q 'W::a' && echo "$names" | grep -q 'W::b'; then
279- echo "queried PHP frames back from pyroscope:"; echo "$names"; break
280- fi
281- sleep 3
282- done
283- kill "$PFP_PID" "$PHP_PID" 2>/dev/null || true
165+ - name : smoke (pyroscope)
166+ run : ./scripts/ci/smoke-pyroscope.sh ./target/release/pfp
0 commit comments