| 1 | name: DCO |
| 2 | |
| 3 | on: |
| 4 | pull_request: |
| 5 | types: [opened, synchronize, reopened] |
| 6 | |
| 7 | permissions: |
| 8 | pull-requests: write |
| 9 | |
| 10 | jobs: |
| 11 | dco: |
| 12 | name: Check Signed-off-by |
| 13 | runs-on: ubuntu-latest |
| 14 | steps: |
| 15 | - uses: actions/checkout@v4 |
| 16 | with: |
| 17 | repository: ${{ github.event.pull_request.head.repo.full_name }} |
| 18 | ref: ${{ github.event.pull_request.head.sha }} |
| 19 | fetch-depth: 0 |
| 20 | |
| 21 | - name: Report missing Signed-off-by (dry-run advisory) |
| 22 | shell: bash |
| 23 | run: | |
| 24 | set -euo pipefail |
| 25 | |
| 26 | base_rev=$(git merge-base origin/${{ github.base_ref }} HEAD 2>/dev/null || echo "HEAD~1") |
| 27 | echo "✅ merge-base: $base_rev" |
| 28 | echo "" |
| 29 | |
| 30 | bad=() |
| 31 | while IFS= read -r commit; do |
| 32 | msg=$(git log --format=%B -n1 "$commit") |
| 33 | if ! echo "$msg" | grep -qi "^Signed-off-by:"; then |
| 34 | bad+=("$commit") |
| 35 | fi |
| 36 | done < <(git rev-list "${base_rev}..HEAD") |
| 37 | |
| 38 | if [ ${#bad[@]} -eq 0 ]; then |
| 39 | echo "✅ All commits have Signed-off-by." |
| 40 | exit 0 |
| 41 | fi |
| 42 | |
| 43 | echo "⚠️ Advisory — the following commit(s) are missing Signed-off-by:" |
| 44 | for c in "${bad[@]}"; do |
| 45 | echo " • $c $(git log --format=%s -n1 "$c")" |
| 46 | done |
| 47 | echo "" |
| 48 | echo "This check is advisory and does not block merging." |
| 49 | echo "Please amend commits with:" |
| 50 | echo " git commit --amend -s" |
| 51 | echo "See CONTRIBUTING.md for details." |
| 52 | echo "" |
| 53 | echo "::warning title=DCO: missing Signed-off-by::Some commits are missing Signed-off-by — amend with git commit --amend -s" |
| 54 | |
| 55 | # Dry-run: always pass, but surface the warning |
| 56 | exit 0 |
| 57 |