Skip to content
Open
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
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ 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.
- Commit signature must be valid. Configured via the `check_signature` input.
When enabled, invalid signatures will cause a failure (missing are ignored).

## Inputs

Expand All @@ -42,6 +44,11 @@ All inputs are optional.
- Check if pull request comes from a feature branch.
- Default: `true`.

### `check_signature`

- Validate commit signatures. Invalid signatures fail, missing are ignored.
- Default: `false`.

### `check_signoff`

- Check if `Signed-off-by` exists and matches author.
Expand Down
5 changes: 5 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ inputs:
description: 'Check if pull request comes from a feature branch'
default: 'true'
required: false
check_signature:
description: 'Validate commit signatures. Invalid signatures fail, missing are ignored.'
default: 'false'
required: false
check_signoff:
description: 'Check if Signed-off-by exists and matches author'
default: 'false'
Expand Down Expand Up @@ -80,6 +84,7 @@ runs:
ACTION_PATH: ${{ github.action_path }}
BASE_BRANCH: origin/${{ github.base_ref }}
CHECK_BRANCH: ${{ inputs.check_branch }}
CHECK_SIGNATURE: ${{ inputs.check_signature }}
CHECK_SIGNOFF: ${{ inputs.check_signoff }}
EXCLUDE_DEPENDABOT: ${{ inputs.exclude_dependabot }}
EXCLUDE_WEBLATE: ${{ inputs.exclude_weblate }}
Expand Down
41 changes: 38 additions & 3 deletions src/check_formalities.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ MAX_SUBJECT_LEN_SOFT=${MAX_SUBJECT_LEN_SOFT:-50}
MAX_BODY_LINE_LEN=${MAX_BODY_LINE_LEN:-75}

CHECK_BRANCH=${CHECK_BRANCH:-true}
CHECK_SIGNATURE=${CHECK_SIGNATURE:-false}
CHECK_SIGNOFF=${CHECK_SIGNOFF:-false}
EXCLUDE_DEPENDABOT=${EXCLUDE_DEPENDABOT:-false}
EXCLUDE_WEBLATE=${EXCLUDE_WEBLATE:-false}
Expand Down Expand Up @@ -74,7 +75,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 @@ -209,12 +210,16 @@ output_split_fail_ex() {
# shellcheck disable=SC2329
check_branch() { [ "$CHECK_BRANCH" = 'true' ]; }
# shellcheck disable=SC2329
check_signature() { [ "$CHECK_SIGNATURE" = 'true' ]; }
# shellcheck disable=SC2329
check_signoff() { [ "$CHECK_SIGNOFF" = '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_signature() { ! check_signature; }
# shellcheck disable=SC2329
ends_with_period() { [[ "$1" =~ \.$ ]]; }
exclude_dependabot() { [ "$EXCLUDE_DEPENDABOT" = 'true' ]; }
exclude_weblate() { [ "$EXCLUDE_WEBLATE" = 'true' ]; }
Expand Down Expand Up @@ -244,7 +249,10 @@ 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_body_empty() {
local line
Expand Down Expand Up @@ -556,6 +564,30 @@ check_body() {
-warn-actual "a stable branch (\`${BASE_BRANCH#origin/}\`)"
}

check_commit_signature() {
local status="$1"
local reason

case "$status" in
B) reason='bad signature' ;;
E) reason='signature cannot be checked' ;;
R) reason='revoked key signature' ;;
U) reason='good signature, validity unknown' ;;
X) reason='good signature, expired' ;;
Y) reason='good signature, expired key' ;;
*) reason='no signature' ;;
esac
Comment on lines +571 to +579
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, this is very good! I was thinking how to do this this way. Thanks!


check \
-rule 'Commit signature must be valid' \
-skip-if do_not_check_signature \
-skip-reason 'disabled by configuration' \
-fail-if is_bad_sign "$status" \
-fail-actual "$reason" \
-warn-if is_warn_sign "$status" \
-warn-actual "$reason"
}

main() {
# Initialize GitHub actions output
output 'content<<EOF'
Expand Down Expand Up @@ -595,7 +627,8 @@ main() {
subject \
body \
sob \
parent_hashes
parent_hashes \
sign_status
do
HEADER_SET=0
COMMIT="$commit"
Expand All @@ -621,6 +654,8 @@ main() {
check_subject "$subject"
reset_skip_reasons "$author_email"
check_body "$body" "$sob"
reset_skip_reasons "$author_email"
check_commit_signature "$sign_status"

echo
done
Expand Down
Loading