Skip to content
Open
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
65 changes: 65 additions & 0 deletions .github/workflows/commit-trailers.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
name: commit-trailers
on:
pull_request:
merge_group:

permissions:
contents: read
pull-requests: read

jobs:
no-ai-coauthor:
runs-on: ubuntu-latest
steps:
- name: Reject AI Co-Authored-By trailers
uses: actions/github-script@v7
with:
script: |
const pr = context.payload.pull_request;
if (!pr) return;
const commits = await github.paginate(github.rest.pulls.listCommits, {
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pr.number,
});
// Known AI coding agents that stamp a `Co-Authored-By:` trailer,
// matched by their vendor email or distinctive bot login. We key on
// bot identities (unambiguous), never on bare human names, so
// legitimate human co-authors are never blocked.
const AI_AGENTS = new RegExp([
'anthropic\\.com', // Claude / Claude Code
'copilot-swe-agent', // GitHub Copilot
'\\+copilot@users\\.noreply', // GitHub Copilot
'devin-ai-integration', // Devin (Cognition)
'cursoragent|@cursor\\.com', // Cursor Agent
'google-labs-jules', // Google Jules / Gemini
'@aider\\.chat', // Aider
'windsurf|codeium', // Windsurf / Codeium
].join('|'), 'i');
const coAuthorLine = /^\s*co-authored-by:.*$/gim;
const offenders = commits
.filter((c) =>
(c.commit.message.match(coAuthorLine) || []).some((l) =>
AI_AGENTS.test(l),
),
)
.map((c) => c.sha.slice(0, 8));
if (offenders.length === 0) {
core.info('No AI Co-Authored-By trailers found.');
return;
}
const msg = [
`Commits ${offenders.join(', ')} carry a "Co-Authored-By: <AI agent>" trailer.`,
'',
'Under US copyright law (which governs CNCF projects) a Co-Authored-By',
'trailer naming an AI agent can attribute rights over the code to its',
'vendor. Use an informational "Assisted-By: <agent>" trailer instead — it',
'discloses AI assistance without transferring authorship.',
'',
'Rationale: https://github.com/anthropics/claude-code/issues/66602',
'',
'Fix: rebase and amend the trailer, then force-push.',
'Prevent it at source: set includeCoAuthoredBy: false in your Claude Code settings.',
].join('\n');
await core.summary.addRaw(msg).write();
core.setFailed(msg);
Loading