From a1463033400a21aeef7be15f08db90522a04cc7f Mon Sep 17 00:00:00 2001 From: Arjav Patel Date: Tue, 24 Feb 2026 11:04:25 +0530 Subject: [PATCH 1/3] tools/checkpatch.sh: Add support for breaking change commit message enforcement - Introduced a new flag '-b' to enforce breaking change format in commit messages. - Added checks to ensure that breaking change commits start with '!' and contain 'BREAKING CHANGE:' in the body before 'Signed-off-by'. - Updated usage instructions to reflect the new breaking change option. Signed-off-by: Arjav Patel --- tools/checkpatch.sh | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/tools/checkpatch.sh b/tools/checkpatch.sh index cce2e6f2d2981..bec4bae760506 100755 --- a/tools/checkpatch.sh +++ b/tools/checkpatch.sh @@ -32,6 +32,7 @@ range=0 spell=0 encoding=0 message=0 +breaking_change=0 # CMake cmake_warning_once=0 @@ -57,6 +58,7 @@ usage() { echo "-r range check only (coupled with -p or -g)" echo "-p (default)" echo "-m Check commit message (coupled with -g)" + echo "-b Enforce breaking change format when checking commit message (requires -m -g; use when PR has breaking change label)" echo "-g " echo "-f " echo "-x format supported files (only .py, requires: pip install black)" @@ -286,13 +288,14 @@ check_msg() { num_lines=0 max_line_len=80 min_num_lines=5 + breaking_change_found=0 first=$(head -n1 <<< "$msg") # check for Merge line and remove from parsed string if [[ $first == *Merge* ]]; then msg="$(echo "$msg" | tail -n +2)" - first=$(head -n2 <<< "$msg") + first=$(head -n1 <<< "$msg") fi while IFS= read -r REPLY; do @@ -311,7 +314,15 @@ check_msg() { fail=1 fi + if [[ $REPLY =~ ^BREAKING\ CHANGE: ]]; then + breaking_change_found=1 + fi + if [[ $REPLY =~ ^Signed-off-by ]]; then + if [ $breaking_change != 0 ] && [ $breaking_change_found == 0 ]; then + echo "❌ BREAKING CHANGE: must appear in the commit body before Signed-off-by (see CONTRIBUTING.md 1.13)" + fail=1 + fi signedoffby_found=1 fi @@ -328,6 +339,23 @@ check_msg() { fail=1 fi + second=$(echo "$msg" | sed -n '2p') + if [ $num_lines -ge 2 ] && ! [[ "$second" =~ ^[[:space:]]*$ ]]; then + echo "❌ Commit subject must be followed by a blank line" + fail=1 + fi + + if [ $breaking_change != 0 ]; then + if [[ "${first:0:1}" != "!" ]]; then + echo "❌ Breaking change commit subject must start with '!' (e.g. '!subsystem: description')" + fail=1 + fi + if [ $breaking_change_found == 0 ]; then + echo "❌ Breaking change commit must contain 'BREAKING CHANGE:' in the body before Signed-off-by (see CONTRIBUTING.md 1.13)" + fail=1 + fi + fi + if ! [ $signedoffby_found == 1 ]; then echo "❌ Missing Signed-off-by" fail=1 @@ -383,6 +411,9 @@ while [ ! -z "$1" ]; do -m ) message=1 ;; + -b ) + breaking_change=1 + ;; -g ) check=check_commit ;; From c0ed2ac250aab01846896998e8d78e61522560e9 Mon Sep 17 00:00:00 2001 From: Arjav Patel Date: Tue, 24 Feb 2026 11:20:04 +0530 Subject: [PATCH 2/3] github/workflows/check.yml: Enhance checkpatch for breaking change labels - Updated the check workflow to conditionally include a '-b' option for breaking change enforcement based on PR labels. - Modified the checkpatch script to support reading commit messages from stdin when using the '-m -g' flags. - Improved usage instructions to clarify the new stdin option for commit message checks. Signed-off-by: Arjav Patel --- .github/workflows/check.yml | 8 ++++++-- tools/checkpatch.sh | 12 +++++++++++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 7f7ecbaf836a5..422fc7927afb6 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -45,5 +45,9 @@ jobs: cd nuttx commits="${{ github.event.pull_request.base.sha }}..HEAD" git log --oneline $commits - echo "../nuttx/tools/checkpatch.sh -c -u -m -g $commits" - ../nuttx/tools/checkpatch.sh -c -u -m -g $commits + breaking_opts="" + if echo '${{ toJSON(github.event.pull_request.labels) }}' | jq -e 'any(.[].name; test("breaking change"; "i"))' >/dev/null 2>&1; then + breaking_opts="-b" + fi + echo "../nuttx/tools/checkpatch.sh -c -u -m -g $breaking_opts $commits" + ../nuttx/tools/checkpatch.sh -c -u -m -g $breaking_opts $commits diff --git a/tools/checkpatch.sh b/tools/checkpatch.sh index bec4bae760506..f2865aaa0e50b 100755 --- a/tools/checkpatch.sh +++ b/tools/checkpatch.sh @@ -60,6 +60,7 @@ usage() { echo "-m Check commit message (coupled with -g)" echo "-b Enforce breaking change format when checking commit message (requires -m -g; use when PR has breaking change label)" echo "-g " + echo " Use --stdin as the only argument with -m -g to read commit message from stdin (message-only check, no patch/diff)." echo "-f " echo "-x format supported files (only .py, requires: pip install black)" echo "- read standard input mainly used by git pre-commit hook as below:" @@ -286,6 +287,7 @@ check_patch() { check_msg() { signedoffby_found=0 num_lines=0 + # Commit subject line length limit (50/72 are common; NuttX uses 80) max_line_len=80 min_num_lines=5 breaking_change_found=0 @@ -420,6 +422,9 @@ while [ ! -z "$1" ]; do -h ) usage 0 ;; + --stdin ) + break + ;; -p ) check=check_patch ;; @@ -437,7 +442,12 @@ while [ ! -z "$1" ]; do done for arg in $@; do - $check $arg + if [ "$arg" = "--stdin" ] && [ "$check" = "check_commit" ]; then + msg=$(cat) + check_msg <<< "$msg" + else + $check $arg + fi done if [ $fail == 1 ]; then From 16d52fc2bd59d9d2017dcb25aaf231697a24e84d Mon Sep 17 00:00:00 2001 From: Arjav Patel Date: Mon, 2 Mar 2026 21:55:52 +0530 Subject: [PATCH 3/3] tools/checkpatch.sh: Enhance stdin support for patch checking - Added functionality to read patch content from stdin when using the '--stdin' option with the '-p' flag. - Updated usage instructions to clarify the new stdin option for patch checks. - Improved error handling for unsupported combinations of options. Signed-off-by: Arjav Patel --- tools/checkpatch.sh | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/tools/checkpatch.sh b/tools/checkpatch.sh index f2865aaa0e50b..a84dfc379e61f 100755 --- a/tools/checkpatch.sh +++ b/tools/checkpatch.sh @@ -61,6 +61,7 @@ usage() { echo "-b Enforce breaking change format when checking commit message (requires -m -g; use when PR has breaking change label)" echo "-g " echo " Use --stdin as the only argument with -m -g to read commit message from stdin (message-only check, no patch/diff)." + echo " Use --stdin with -p to read patch content from stdin." echo "-f " echo "-x format supported files (only .py, requires: pip install black)" echo "- read standard input mainly used by git pre-commit hook as below:" @@ -442,9 +443,25 @@ while [ ! -z "$1" ]; do done for arg in $@; do - if [ "$arg" = "--stdin" ] && [ "$check" = "check_commit" ]; then - msg=$(cat) - check_msg <<< "$msg" + if [ "$arg" = "--stdin" ]; then + case "$check" in + check_commit) + msg=$(cat) + check_msg <<< "$msg" + ;; + check_patch) + tmp=$(mktemp) + trap "rm -f $tmp" EXIT + cat > "$tmp" + check_patch "$tmp" + rm -f "$tmp" + trap - EXIT + ;; + check_file|format_file) + echo "❌ --stdin is only supported with -g (commit message) or -p (patch)" + fail=1 + ;; + esac else $check $arg fi