Skip to content

ci: add DCO sign-off check workflow#941

Open
brandonpelfrey wants to merge 3 commits intoNVIDIA:mainfrom
brandonpelfrey:dco-check
Open

ci: add DCO sign-off check workflow#941
brandonpelfrey wants to merge 3 commits intoNVIDIA:mainfrom
brandonpelfrey:dco-check

Conversation

@brandonpelfrey
Copy link
Copy Markdown
Collaborator

@brandonpelfrey brandonpelfrey commented Mar 26, 2026

Summary

Add CI DCO check which is manually verified by maintainers today.

Related Issue

Fixed #889

Changes

  • Add workflow DCO check asserts that author email also appears in DCO signed-off-by

Type of Change

  • Code change for a new feature, bug fix, or refactor.
  • Code change with doc updates.
  • Doc only. Prose changes without code sample modifications.
  • Doc only. Includes code sample changes.

Testing

  • npx prek run --all-files passes (or equivalently make check).
  • npm test passes.
  • make docs builds without warnings. (for doc-only changes)
  • CI

Checklist

General

Code Changes

  • Formatters applied — npx prek run --all-files auto-fixes formatting (or make format for targeted runs).
  • Tests added or updated for new or changed behavior.
  • No secrets, API keys, or credentials committed.
  • Doc pages updated for any user-facing behavior changes (new commands, changed defaults, new features, bug fixes that contradict existing docs).

Doc Changes

  • Follows the style guide. Try running the update-docs agent skill to draft changes while complying with the style guide. For example, prompt your agent with "/update-docs catch up the docs for the new changes I made in this PR."
  • New pages include SPDX license header and frontmatter, if creating a new page.
  • Cross-references and links verified.

Summary by CodeRabbit

  • Chores
    • Added automated Developer Certificate of Origin (DCO) sign-off validation for pull requests. Commits are checked for matching sign-off metadata; any non-compliant commits are reported with a list of problematic commits and guidance on how to add proper sign-offs (amend or rebase and sign-off). Pull requests with failures will be marked accordingly to prompt remediation.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 26, 2026

📝 Walkthrough

Walkthrough

Added a new GitHub Actions workflow that runs on pull request events and validates that every non-merge commit between the PR base and head contains a Signed-off-by: trailer matching the commit author email; it reports violations with remediation steps and fails the check if any are found.

Changes

Cohort / File(s) Summary
DCO Compliance Workflow
.github/workflows/dco-check.yaml
Added workflow dco-check triggered on PR events (opened, synchronize, reopened). Uses ubuntu-latest, full repo checkout (fetch-depth: 0), iterates non-merge commits between origin/$BASE_REF and $HEAD_SHA, compares commit author email to Signed-off-by: trailer(s), collects/report violations, exits non-zero on failures. Concurrency and minimum permissions configured.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐇 I hop through commits, line by line,
Checking sign-offs till each one aligns.
If a trailer's missing or emails don't agree,
I'll call it out kindly — fix and push with glee.
Signed, stamped, and ready: merge merrily!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed The PR implements a DCO check workflow that verifies commits have valid Signed-off-by trailers matching author emails, addressing the core coding requirement from issue #889 to enforce DCO compliance.
Out of Scope Changes check ✅ Passed All changes are directly within scope: the new DCO check workflow is the only file modified and directly implements the DCO verification requirement from issue #889.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Title check ✅ Passed The title accurately describes the main change: adding a DCO sign-off check workflow to CI.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
.github/workflows/dco-check.yaml (1)

4-9: Add repo-level enforcement to complete the objective.

This workflow alone does not prevent merges unless branch protection requires this status check (or the DCO GitHub App check) on main.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/dco-check.yaml around lines 4 - 9, The workflow
"dco-check" only defines the pull_request trigger but doesn't enforce merges;
update repo-level protection so the "dco-check" status check is required on
branch "main" (or enable the DCO GitHub App) to block merges without DCO
signoff—go to branch protection settings and add the "dco-check" workflow as a
required status check for main (or install/configure the DCO app) so the
pull_request runs become blocking.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/dco-check.yaml:
- Around line 35-41: The current extraction uses grep -m1 to set signoff_email,
which only checks the first Signed-off-by trailer; instead collect all
Signed-off-by emails from the commit body (replace the grep -m1 usage that
assigns signoff_email) and test whether any of those emails equals author_email,
then mark the commit bad if none match; update the branch of logic that
currently compares "$signoff_email" to "$author_email" to check membership in
the list of extracted sign-off emails, keeping the existing bad+="..." and
failed=1 behavior when no match is found.
- Around line 22-33: The DCO check iterates commits using the range
"$BASE_SHA"..HEAD which can include the synthetic merge commit; fix by
explicitly targeting the PR head SHA instead of HEAD: add an env var from
github.event.pull_request.head.sha (e.g. PR_HEAD_SHA) and replace the git
rev-list range "$BASE_SHA"..HEAD with "$BASE_SHA".."$PR_HEAD_SHA" (use the
PR_HEAD_SHA env) so only real PR commits are checked; update the run block that
contains the for sha in $(git rev-list "$BASE_SHA"..HEAD) loop to use the new
PR_HEAD_SHA variable.

---

Nitpick comments:
In @.github/workflows/dco-check.yaml:
- Around line 4-9: The workflow "dco-check" only defines the pull_request
trigger but doesn't enforce merges; update repo-level protection so the
"dco-check" status check is required on branch "main" (or enable the DCO GitHub
App) to block merges without DCO signoff—go to branch protection settings and
add the "dco-check" workflow as a required status check for main (or
install/configure the DCO app) so the pull_request runs become blocking.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 976577b8-89bb-4858-b945-775227544486

📥 Commits

Reviewing files that changed from the base of the PR and between a1b86a5 and c1288d0.

📒 Files selected for processing (1)
  • .github/workflows/dco-check.yaml

Signed-off-by: Brandon Pelfrey <bpelfrey@nvidia.com>
@brandonpelfrey brandonpelfrey changed the title Add DCO signoff CI check ci: add DCO sign-off check workflow Mar 26, 2026
@cv
Copy link
Copy Markdown
Contributor

cv commented Mar 26, 2026

Consider: skip per-commit DCO checks — enforce sign-off on the squash commit instead

This repo is squash-merge only. That means every PR becomes a single commit on main — the individual branch commits are thrown away. Requiring DCO on each branch commit is friction for no gain, since those commits won't exist on main.

What matters

The Signed-off-by: trailer needs to be on the squash commit that lands on main, not on throwaway branch commits.

How to do it

GitHub has a repo-level setting that controls what goes into the squash commit message body. Currently this repo uses COMMIT_MESSAGES (concatenates branch commit messages). If we switch it to PR_BODY, the squash commit message comes from the PR description:

gh api repos/nvidia/nemoclaw -X PATCH -f squash_merge_commit_message=PR_BODY

With that in place:

  1. PR template — add a Signed-off-by: line to the PR template so contributors fill it in (or a bot pre-fills it from their git config).
  2. CI check on the PR body — a simpler GHA that just validates the PR description contains a valid Signed-off-by: line:
name: DCO Sign-off
on:
  pull_request:
    types: [opened, edited, synchronize]

jobs:
  dco:
    runs-on: ubuntu-latest
    steps:
      - name: Check PR body for Signed-off-by
        env:
          PR_BODY: ${{ github.event.pull_request.body }}
        run: |
          if ! echo "$PR_BODY" | grep -qP '^Signed-off-by: .+ <.+>'; then
            echo "::error::PR description must contain a DCO sign-off line:"
            echo "::error::  Signed-off-by: Your Name <your@email.com>"
            exit 1
          fi
  1. Branch protection — require this check to pass before merge (same admin ask as the current approach).

Why this is better

Current PR (per-commit check) PR-body approach
What's checked Every branch commit The PR description (which becomes the squash commit body on main)
Contributor friction Must git commit -s on every commit, fix-up with --amend/rebase --signoff Add one line to PR description
What lands on main Single squash commit — branch commits are gone Single squash commit with Signed-off-by: in the body
DCO coverage on main ❌ Squash commit may not have sign-off (depends on squash message config) ✅ Squash commit inherits sign-off from PR body
Repo setting needed None squash_merge_commit_message=PR_BODY (repo admin)

The per-commit approach has a gap: even if every branch commit is signed off, the resulting squash commit on main might not carry the trailer (depends on the squash message template). The PR-body approach closes that gap by design.

TL;DR

Switch squash_merge_commit_message to PR_BODY, validate sign-off in the PR description, and skip per-commit checks entirely. Less friction for contributors, better DCO coverage on main.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add DCO GitHub App to enforce Developer Certificate of Origin on PRs

2 participants