Files
PX4-Autopilot/.github/workflows/commit_checks.yml
Ramon Roche 4da97eb4fd ci(workflows): add commit message and PR title quality checks
Add CI enforcement of conventional commit format for PR titles and
commit messages. Includes three Python scripts under Tools/ci/:

- conventional_commits.py: shared parsing/validation library
- check_pr_title.py: validates PR title format, suggests fixes
- check_commit_messages.py: checks commits for blocking errors
  (fixup/squash/WIP leftovers) and advisory warnings (review-response,
  formatter-only commits)

The workflow (.github/workflows/commit_checks.yml) posts concise
GitHub PR comments with actionable suggestions and auto-removes them
once issues are resolved.

Also updates CONTRIBUTING.md and docs with the conventional commits
convention.

Signed-off-by: Ramon Roche <mrpollo@gmail.com>
2026-03-06 17:51:54 -08:00

149 lines
5.0 KiB
YAML

name: Commit Quality
on:
pull_request:
types: [opened, edited, synchronize, reopened]
permissions:
contents: read
pull-requests: write
issues: write
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
PR_NUMBER: ${{ github.event.pull_request.number }}
IS_FORK: ${{ github.event.pull_request.head.repo.full_name != github.repository }}
jobs:
pr-title:
name: PR Title
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
sparse-checkout: Tools/ci
fetch-depth: 1
- name: Check PR title
id: check
run: |
python3 Tools/ci/check_pr_title.py "${{ github.event.pull_request.title }}" --markdown-file comment.md && rc=0 || rc=$?
echo "exit_code=$rc" >> "$GITHUB_OUTPUT"
- name: Post or clear comment
if: env.IS_FORK == 'false'
env:
GH_TOKEN: ${{ github.token }}
run: |
if [ "${{ steps.check.outputs.exit_code }}" != "0" ]; then
python3 Tools/ci/pr_comment.py --marker pr-title --pr "$PR_NUMBER" --result fail < comment.md
else
python3 Tools/ci/pr_comment.py --marker pr-title --pr "$PR_NUMBER" --result pass
fi
- name: Result
if: steps.check.outputs.exit_code != '0'
run: |
echo "::error::PR title does not follow conventional commits format. See the PR comment for details."
exit 1
commit-messages:
name: Commit Messages
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
sparse-checkout: Tools/ci
fetch-depth: 1
- name: Check commit messages
id: check
env:
GH_TOKEN: ${{ github.token }}
run: |
gh api \
"repos/${{ github.repository }}/pulls/${PR_NUMBER}/commits?per_page=100" \
| python3 Tools/ci/check_commit_messages.py --markdown-file comment.md && rc=0 || rc=$?
echo "exit_code=$rc" >> "$GITHUB_OUTPUT"
# Check for warnings (non-empty markdown on exit 0)
if [ "$rc" -eq 0 ] && [ -s comment.md ]; then
echo "has_warnings=true" >> "$GITHUB_OUTPUT"
else
echo "has_warnings=false" >> "$GITHUB_OUTPUT"
fi
- name: Post or clear comment
if: env.IS_FORK == 'false'
env:
GH_TOKEN: ${{ github.token }}
run: |
if [ "${{ steps.check.outputs.exit_code }}" != "0" ]; then
python3 Tools/ci/pr_comment.py --marker commit-msgs --pr "$PR_NUMBER" --result fail < comment.md
elif [ "${{ steps.check.outputs.has_warnings }}" == "true" ]; then
python3 Tools/ci/pr_comment.py --marker commit-msgs --pr "$PR_NUMBER" --result warn < comment.md
else
python3 Tools/ci/pr_comment.py --marker commit-msgs --pr "$PR_NUMBER" --result pass
fi
- name: Result
if: steps.check.outputs.exit_code != '0'
run: |
echo "::error::Commit message errors found. See the PR comment for details."
exit 1
pr-body:
name: PR Description
runs-on: ubuntu-latest
steps:
- name: Checkout
if: env.IS_FORK == 'false'
uses: actions/checkout@v4
with:
sparse-checkout: Tools/ci
fetch-depth: 1
- name: Check PR body
id: check
env:
PR_BODY: ${{ github.event.pull_request.body }}
run: |
message=""
if [ -z "$PR_BODY" ]; then
message="PR description is empty. Please add a summary of the changes."
echo "::warning::PR description is empty."
else
cleaned=$(echo "$PR_BODY" | sed 's/<!--.*-->//g' | tr -d '[:space:]')
if [ -z "$cleaned" ]; then
message="PR description contains only template comments. Please fill in the details."
echo "::warning::PR description contains only template comments."
fi
fi
echo "message=$message" >> "$GITHUB_OUTPUT"
- name: Post or clear comment
if: env.IS_FORK == 'false'
env:
GH_TOKEN: ${{ github.token }}
run: |
if [ -n "${{ steps.check.outputs.message }}" ]; then
printf '%s\n' \
"## PR Description (advisory)" \
"" \
"This is **not blocking**, but your PR description appears to be empty or incomplete." \
"" \
"${{ steps.check.outputs.message }}" \
"" \
"A good PR description helps reviewers understand what changed and why." \
"" \
"---" \
"*This comment will be automatically removed once the issue is resolved.*" \
| python3 Tools/ci/pr_comment.py --marker pr-body --pr "$PR_NUMBER" --result warn
else
python3 Tools/ci/pr_comment.py --marker pr-body --pr "$PR_NUMBER" --result pass
fi