Skip to content

Commit ba2e9bf

Browse files
committed
gmentci: add PR stack usage report via puncover
Add scripts and a CI workflow step that compare static stack usage between a PR and its merge base. On each PR, the workflow rebuilds with `CONFIG_STACK_USAGE=y`, runs puncover via `stack_threads.py`, and posts a sticky comment with a per-thread table showing configured size, max static depth, delta vs base, and remaining margin. Thread entry points are discovered from `K_THREAD_DEFINE` in app sources; Zephyr/NCS subsystem stacks are resolved via `rg` in the west tree with a small fallback map. Work queues list configured size only since puncover can't attribute depth per queue. Signed-off-by: Simen S. Røstad <simen.rostad@nordicsemi.no>
1 parent 47257dd commit ba2e9bf

4 files changed

Lines changed: 658 additions & 0 deletions

File tree

.github/workflows/build.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,30 @@ jobs:
280280
header: app-size-report
281281
path: ${{ github.workspace }}/size-comment.md
282282

283+
- name: Install puncover
284+
if: github.event_name == 'pull_request'
285+
run: pip install puncover --break-system-packages
286+
287+
- name: Generate PR stack usage comment for thingy91x image
288+
if: github.event_name == 'pull_request'
289+
env:
290+
BASE_SHA: ${{ github.event.pull_request.base.sha }}
291+
BOARD: thingy91x/nrf9151/ns
292+
PR_APP_DIR: ${{ github.workspace }}/asset-tracker-template/app
293+
STACK_COMMENT_PATH: ${{ github.workspace }}/stack-comment.md
294+
CI_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
295+
run: |
296+
SDK_BIN=$(ls -d /opt/toolchains/zephyr-sdk-*/arm-zephyr-eabi/bin 2>/dev/null | head -1)
297+
[ -n "$SDK_BIN" ] && export PATH="$SDK_BIN:$PATH"
298+
bash asset-tracker-template/scripts/ci/pr-stack-usage.sh
299+
300+
- name: Post PR stack usage sticky comment for thingy91x image
301+
if: github.event_name == 'pull_request'
302+
uses: marocchino/sticky-pull-request-comment@0ea0beb66eb9baf113663a64ec522f60e49231c0 # v3.0.4
303+
with:
304+
header: stack-usage-report
305+
path: ${{ github.workspace }}/stack-comment.md
306+
283307
- name: Upload artifacts
284308
uses: actions/upload-artifact@v4
285309
with:

scripts/ci/pr-stack-usage.sh

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#!/usr/bin/env bash
2+
# Generate a sticky-comment-ready markdown body with puncover static stack usage
3+
# for ATT module threads (PR vs merge base).
4+
#
5+
# Required env vars:
6+
# BASE_SHA, BOARD, STACK_COMMENT_PATH
7+
# PR_APP_DIR path to app/ in this checkout (default: <repo>/app)
8+
# PR_BUILD_DIR existing west build dir for PR head (default: PR_APP_DIR/build)
9+
# Optional:
10+
# CI_RUN_URL
11+
12+
set -euo pipefail
13+
: "${BASE_SHA:?}" "${BOARD:?}" "${STACK_COMMENT_PATH:?}"
14+
15+
REPO_ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
16+
WORKSPACE_DIR="$(cd "$REPO_ROOT/.." && pwd)"
17+
PR_APP_DIR="${PR_APP_DIR:-$REPO_ROOT/app}"
18+
# Separate from the release build dir so we do not disturb CI firmware artifacts.
19+
PR_STACK_BUILD_DIR="${PR_STACK_BUILD_DIR:-$PR_APP_DIR/build-stack-analysis}"
20+
BASELINE_STACK_BUILD_DIR="${BASELINE_STACK_BUILD_DIR:-$PR_APP_DIR/build-baseline-stack}"
21+
STACK_DIR="${STACK_DIR:-$(dirname "$STACK_COMMENT_PATH")/stack}"
22+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
23+
24+
mkdir -p "$STACK_DIR" "$(dirname "$STACK_COMMENT_PATH")"
25+
PR_SHA=$(git -C "$REPO_ROOT" rev-parse HEAD)
26+
27+
write_failure_comment() {
28+
echo "Stack usage report failed. See [CI run](${CI_RUN_URL:-}) for logs." >"$STACK_COMMENT_PATH"
29+
}
30+
31+
stack_build() {
32+
local build_dir="$1"
33+
rm -rf "$build_dir"
34+
(cd "$PR_APP_DIR" && west build -p --sysbuild -b "$BOARD" -d "$build_dir" -- \
35+
-DCONFIG_STACK_USAGE=y 2>&1)
36+
}
37+
38+
run_report() {
39+
local elf="$1" build_dir="$2" config="$3" out="$4"
40+
bash "$SCRIPT_DIR/run-puncover-stack-report.sh" \
41+
"$elf" "$build_dir/app" "$config" "$out" "$PR_APP_DIR"
42+
}
43+
44+
(
45+
# Rebuild with CONFIG_STACK_USAGE=y so GCC emits .su files for puncover.
46+
stack_build "$PR_STACK_BUILD_DIR" | tee "$STACK_DIR/pr_stack_build.log"
47+
run_report \
48+
"$PR_STACK_BUILD_DIR/app/zephyr/zephyr.elf" \
49+
"$PR_STACK_BUILD_DIR" \
50+
"$PR_STACK_BUILD_DIR/app/zephyr/.config" \
51+
"$STACK_DIR/pr_stack.json"
52+
53+
git -C "$REPO_ROOT" fetch --depth=1 origin "$BASE_SHA"
54+
git -C "$REPO_ROOT" checkout --detach "$BASE_SHA"
55+
(cd "$WORKSPACE_DIR" && west update -o=--depth=1 -n)
56+
stack_build "$BASELINE_STACK_BUILD_DIR" | tee "$STACK_DIR/baseline_stack_build.log"
57+
run_report \
58+
"$BASELINE_STACK_BUILD_DIR/app/zephyr/zephyr.elf" \
59+
"$BASELINE_STACK_BUILD_DIR" \
60+
"$BASELINE_STACK_BUILD_DIR/app/zephyr/.config" \
61+
"$STACK_DIR/baseline_stack.json"
62+
git -C "$REPO_ROOT" checkout --detach "$PR_SHA"
63+
64+
python3 "$SCRIPT_DIR/stack_threads.py" format-comment \
65+
"$STACK_DIR/pr_stack.json" \
66+
"$STACK_DIR/baseline_stack.json" \
67+
"$PR_APP_DIR" \
68+
--config "$PR_STACK_BUILD_DIR/app/zephyr/.config" \
69+
--west "$WORKSPACE_DIR" \
70+
--ci-url "${CI_RUN_URL:-}" \
71+
>"$STACK_COMMENT_PATH"
72+
) || write_failure_comment
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#!/usr/bin/env bash
2+
# Run puncover static stack analysis (threads discovered from app sources).
3+
#
4+
# Usage: run-puncover-stack-report.sh <elf> <build_dir> <zephyr.config> <output.json> <app_dir>
5+
6+
set -euo pipefail
7+
8+
ELF="${1:?elf}"
9+
BUILD_DIR="${2:?build_dir}"
10+
CONFIG_FILE="${3:?config}"
11+
OUTPUT_JSON="${4:?output.json}"
12+
APP_DIR="${5:?app_dir}"
13+
14+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
15+
16+
if ! command -v puncover >/dev/null 2>&1; then
17+
echo "puncover not found on PATH" >&2
18+
exit 1
19+
fi
20+
21+
WEST_DIR="${WEST_DIR:-$(cd "$APP_DIR/../.." && pwd)}"
22+
23+
python3 "$SCRIPT_DIR/stack_threads.py" report \
24+
"$ELF" "$BUILD_DIR" "$CONFIG_FILE" "$OUTPUT_JSON" "$APP_DIR" \
25+
--west "$WEST_DIR"

0 commit comments

Comments
 (0)