Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ Commit & PR formalities checker based on the OpenWrt [submission guidelines](
- Commit message lines should be <= `MAX_BODY_LINE_LEN` characters long. Limit
is 75 by default and is configurable via the `max_body_line_len` input.
- Commit to stable branch should be marked as cherry-picked.
- Verifies commit signature (GPG/SSH) if present. Missing signatures are ignored, but invalid signatures will cause a failure.
- Modified files must end with a newline. Configured via the `check_trailing_newline` input.
- Modified files must not contain trailing whitespace. Configured via the `check_trailing_whitespace` input.

## Inputs

Expand All @@ -47,6 +50,16 @@ All inputs are optional.
- Check if `Signed-off-by` exists and matches author.
- Default: `false`.

### `check_trailing_newline`

- Check if modified files end with a newline.
- Default: `true`.

### `check_trailing_whitespace`

- Check if modified files contain trailing whitespace.
- Default: `true`.

### `exclude_dependabot`

- Exclude commits authored by dependabot from some checks.
Expand Down
69 changes: 63 additions & 6 deletions src/check_formalities.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ MAX_BODY_LINE_LEN=${MAX_BODY_LINE_LEN:-75}

CHECK_BRANCH=${CHECK_BRANCH:-true}
CHECK_SIGNOFF=${CHECK_SIGNOFF:-false}
CHECK_TRAILING_NEWLINE=${CHECK_TRAILING_NEWLINE:-true}
CHECK_TRAILING_WHITESPACE=${CHECK_TRAILING_WHITESPACE:-true}
EXCLUDE_DEPENDABOT=${EXCLUDE_DEPENDABOT:-false}
EXCLUDE_WEBLATE=${EXCLUDE_WEBLATE:-false}
SHOW_LEGEND=${SHOW_LEGEND:-true}
Expand Down Expand Up @@ -67,7 +69,7 @@ _R=$'\xfa'
GIT_HEADER='%C(yellow)commit %H%n%C(reset)Author: %an <%ae>%nCommit: %cn <%ce>%n%n%w(0,4,4)%B'
# GH actions sometimes return a mix of body %b and raw body %B when body is
# requested, so always use raw body
GIT_VARS="%H${_F}%aN${_F}%aE${_F}%cN${_F}%cE${_F}%s${_F}%B${_F}Signed-off-by: %aN <%aE>${_F}%P"
GIT_VARS="%H${_F}%aN${_F}%aE${_F}%cN${_F}%cE${_F}%s${_F}%B${_F}Signed-off-by: %aN <%aE>${_F}%P${_F}%G?"
GIT_FORMAT="${_F}${GIT_HEADER}${_F}${GIT_VARS}${_R}"

ACTION_PATH=${ACTION_PATH:+"$ACTION_PATH/src"}
Expand Down Expand Up @@ -193,13 +195,21 @@ output_split_fail_ex() {
}

# shellcheck disable=SC2329
check_branch() { [ "$CHECK_BRANCH" = 'true' ]; }
check_branch() { [ "$CHECK_BRANCH" = 'true' ]; }
# shellcheck disable=SC2329
check_signoff() { [ "$CHECK_SIGNOFF" = 'true' ]; }
check_signoff() { [ "$CHECK_SIGNOFF" = 'true' ]; }
# shellcheck disable=SC2329
do_not_check_branch() { ! check_branch; }
check_trailing_newline() { [ "$CHECK_TRAILING_NEWLINE" = 'true' ]; }
# shellcheck disable=SC2329
do_not_check_signoff() { ! check_signoff; }
check_trailing_whitespace() { [ "$CHECK_TRAILING_WHITESPACE" = 'true' ]; }
# shellcheck disable=SC2329
do_not_check_branch() { ! check_branch; }
# shellcheck disable=SC2329
do_not_check_signoff() { ! check_signoff; }
# shellcheck disable=SC2329
do_not_check_trailing_newline() { ! check_trailing_newline; }
# shellcheck disable=SC2329
do_not_check_trailing_whitespace(){ ! check_trailing_whitespace; }
# shellcheck disable=SC2329
ends_with_period() { [[ "$1" =~ \.$ ]]; }
exclude_dependabot() { [ "$EXCLUDE_DEPENDABOT" = 'true' ]; }
Expand Down Expand Up @@ -230,6 +240,16 @@ show_legend() { [ "$SHOW_LEGEND" = 'true' ]; }
show_feedback() { [ -n "$FEEDBACK_URL" ]; }
# shellcheck disable=SC2329
starts_with_space() { [[ "$1" =~ ^[[:space:]] ]]; }
# shellcheck disable=SC2329
is_bad_sign() { [[ "$1" =~ ^[BRE]$ ]]; }
# shellcheck disable=SC2329
is_warn_sign() { [[ "$1" =~ ^[UXY]$ ]]; }
# shellcheck disable=SC2329
is_unsigned() { [ "$1" = 'N' ]; }
# shellcheck disable=SC2329
has_missing_newline() { git show --pretty=format: "$1" | grep -q "\\ No newline at end of file"; }
# shellcheck disable=SC2329
has_trailing_whitespace(){ git show --check --pretty=format: "$1" >/dev/null 2>&1 && return 1; return 0; }

# shellcheck disable=SC2329
is_body_empty() {
Expand Down Expand Up @@ -542,6 +562,38 @@ check_body() {
-warn-actual "a stable branch (\`${BASE_BRANCH#origin/}\`)"
}

check_signature() {
local status="$1"

check \
-rule 'Signature must be valid' \
-skip-if is_unsigned "$status" \
-skip-reason 'No signature' \
-fail-if is_bad_sign "$status" \
-fail-actual "Bad/Revoked/Error signature (Status: $status)" \
-warn-if is_warn_sign "$status" \
-warn-actual "Expired/Unknown signature (Status: $status)" \
-pass-reason 'Good signature'
}

check_content() {
local commit="$1"

check \
-rule 'Modified files must end with a newline' \
-skip-if do_not_check_trailing_newline \
-skip-reason 'disabled by configuration' \
-fail-if has_missing_newline "$commit" \
-fail-actual 'No newline at end of file'

check \
-rule 'Modified files must not contain trailing whitespace' \
-skip-if do_not_check_trailing_whitespace \
-skip-reason 'disabled by configuration' \
-warn-if has_trailing_whitespace "$commit" \
-warn-actual 'Trailing whitespace found'
}

main() {
# Initialize GitHub actions output
output 'content<<EOF'
Expand Down Expand Up @@ -581,7 +633,8 @@ main() {
subject \
body \
sob \
parent_hashes
parent_hashes \
sign_status
do
HEADER_SET=0
COMMIT="$commit"
Expand All @@ -607,6 +660,10 @@ main() {
check_subject "$subject"
reset_skip_reasons "$author_email"
check_body "$body" "$sob"
reset_skip_reasons "$author_email"
check_signature "$sign_status"
reset_skip_reasons "$author_email"
check_content "$commit"

echo
done
Expand Down
Loading
Loading