mirror of
https://github.com/ashishpatel26/500-AI-Agents-Projects.git
synced 2026-09-02 22:34:04 +08:00
ci: require DCO sign-off on every pull request (#153)
Adds a Developer Certificate of Origin check. Every non-merge commit in a PR must carry a Signed-off-by line matching its author, which is what git commit -s produces. Chose DCO over a CLA deliberately. A CLA means collecting and storing contributor names and email addresses, which is personal data this project would then be responsible for - a heavy obligation for a repo where most contributions are a single table row. DCO makes the same assertion, that the contributor has the right to submit the work, with nothing stored beyond the commit itself. Implemented with actions/github-script rather than a third-party action so there is no external dependency in the merge path. Merge commits are skipped since GitHub generates them. On failure the check writes a job summary naming the offending commits and the exact rebase command to fix them. Signed-off-by: ashishpatel26 <3095771+ashishpatel26@users.noreply.github.com> Co-authored-by: ashishpatel26 <3095771+ashishpatel26@users.noreply.github.com>
This commit is contained in:
68
.github/workflows/dco.yml
vendored
Normal file
68
.github/workflows/dco.yml
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
name: DCO
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
|
||||
jobs:
|
||||
DCO:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check every commit is signed off
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const commits = await github.paginate(
|
||||
github.rest.pulls.listCommits,
|
||||
{ ...context.repo, pull_number: context.payload.pull_request.number }
|
||||
);
|
||||
|
||||
const unsigned = [];
|
||||
for (const c of commits) {
|
||||
// Merge commits are generated by GitHub, not authored by the contributor.
|
||||
if (c.parents && c.parents.length > 1) continue;
|
||||
|
||||
const author = c.commit.author;
|
||||
const expected = `Signed-off-by: ${author.name} <${author.email}>`;
|
||||
const hasSignoff = c.commit.message
|
||||
.split('\n')
|
||||
.some(line => line.trim().toLowerCase() === expected.toLowerCase());
|
||||
|
||||
if (!hasSignoff) {
|
||||
unsigned.push(`${c.sha.slice(0, 7)} ${c.commit.message.split('\n')[0]}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (unsigned.length === 0) {
|
||||
core.info(`All ${commits.length} commit(s) signed off.`);
|
||||
return;
|
||||
}
|
||||
|
||||
core.summary.addHeading('DCO check failed', 2);
|
||||
core.summary.addRaw(
|
||||
'These commits are missing a `Signed-off-by` line matching their author:'
|
||||
);
|
||||
core.summary.addCodeBlock(unsigned.join('\n'));
|
||||
core.summary.addRaw([
|
||||
'',
|
||||
'Sign off your existing commits and force-push:',
|
||||
'',
|
||||
'```bash',
|
||||
'git rebase --signoff origin/main',
|
||||
'git push --force-with-lease',
|
||||
'```',
|
||||
'',
|
||||
'For future commits, `git commit -s` adds the line automatically.',
|
||||
'',
|
||||
'The sign-off certifies you wrote the contribution or have the right to',
|
||||
'submit it under the repository\'s MIT licence. Full text: https://developercertificate.org/'
|
||||
].join('\n'));
|
||||
await core.summary.write();
|
||||
|
||||
core.setFailed(
|
||||
`${unsigned.length} of ${commits.length} commit(s) missing a valid Signed-off-by line.`
|
||||
);
|
||||
@@ -107,12 +107,42 @@ requirements: requirements.txt
|
||||
## PR process and checklist
|
||||
Before opening a PR:
|
||||
- [ ] Fork and create a branch: feat/<short-desc> or fix/<short-desc>
|
||||
- [ ] Sign off every commit with `git commit -s` (see below)
|
||||
- [ ] Update README and metadata
|
||||
- [ ] Paste real sample output from a run into your agent's README
|
||||
- [ ] Ensure no secrets or private data are included
|
||||
- [ ] Rebase onto current `main` — README moves fast and stale branches conflict
|
||||
- [ ] Confirm license compatibility for added assets
|
||||
|
||||
### Sign your commits (DCO)
|
||||
|
||||
Every commit needs a `Signed-off-by` line. Use `-s` and git adds it for you:
|
||||
|
||||
```bash
|
||||
git commit -s -m "add my agent"
|
||||
```
|
||||
|
||||
Which appends:
|
||||
|
||||
```
|
||||
Signed-off-by: Your Name <you@example.com>
|
||||
```
|
||||
|
||||
Forgot on commits you already pushed? Fix them all at once:
|
||||
|
||||
```bash
|
||||
git rebase --signoff origin/main
|
||||
git push --force-with-lease
|
||||
```
|
||||
|
||||
Set `git config user.name` and `git config user.email` first, since the sign-off must
|
||||
match the commit author. A CI check enforces this on every PR.
|
||||
|
||||
This is the [Developer Certificate of Origin](https://developercertificate.org/) — by
|
||||
signing off you're stating that you wrote the contribution, or otherwise have the right
|
||||
to submit it under this repository's MIT licence. There's no separate form to fill in
|
||||
and nothing is stored beyond the commit itself.
|
||||
|
||||
PR description should include:
|
||||
- What changed and why
|
||||
- How to run the example(s) and tests
|
||||
|
||||
Reference in New Issue
Block a user