Skip to content

Commit f294d0e

Browse files
paradoxboundParadoxboundclaude
authored
feat: add DCO sign-off requirement (OSPS-LE-01.01) (#67)
Adds a DCO check workflow that fails PRs containing commits without a Signed-off-by line. Updates CONTRIBUTING.md with instructions for git commit -s and git rebase --signoff. After merging, add 'DCO sign-off' as a required status check in GitHub Settings > Branches > main. Co-authored-by: Paradoxbound <paradoxbound@paradoxbound.org> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 29a9f06 commit f294d0e

2 files changed

Lines changed: 68 additions & 1 deletion

File tree

.github/workflows/dco.yml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
name: DCO Check
2+
3+
on:
4+
pull_request:
5+
branches: [main]
6+
7+
permissions:
8+
contents: read
9+
pull-requests: read
10+
11+
jobs:
12+
dco:
13+
name: DCO sign-off
14+
runs-on: ubuntu-latest
15+
16+
steps:
17+
- name: Harden the runner (Audit all outbound calls)
18+
uses: step-security/harden-runner@a90bcbc6539c36a85cdfeb73f7e2f433735f215b # v2.15.0
19+
with:
20+
egress-policy: audit
21+
22+
- name: Check all commits for Signed-off-by
23+
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7
24+
with:
25+
script: |
26+
const commits = await github.rest.pulls.listCommits({
27+
owner: context.repo.owner,
28+
repo: context.repo.repo,
29+
pull_number: context.issue.number,
30+
per_page: 100,
31+
});
32+
33+
const unsigned = commits.data.filter(({ commit }) =>
34+
!commit.message.includes('Signed-off-by:')
35+
);
36+
37+
if (unsigned.length > 0) {
38+
const list = unsigned
39+
.map(({ sha, commit }) => ` - ${sha.slice(0, 7)}: ${commit.message.split('\n')[0]}`)
40+
.join('\n');
41+
core.setFailed(
42+
`${unsigned.length} commit(s) missing a DCO Signed-off-by line:\n${list}\n\n` +
43+
`Please add 'Signed-off-by: Your Name <your@email.com>' to each commit.\n` +
44+
`Use 'git commit -s' to sign off automatically, or 'git rebase --signoff HEAD~N' to fix existing commits.`
45+
);
46+
} else {
47+
console.log(`All ${commits.data.length} commit(s) have a valid DCO sign-off.`);
48+
}

CONTRIBUTING.md

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,32 @@ npm run type-check
1717
- `packages/core/` — BookStack API client and shared types (no runtime dependencies)
1818
- `packages/stdio/` — MCP server with stdio transport
1919

20+
## Developer Certificate of Origin (DCO)
21+
22+
All commits must include a `Signed-off-by` line asserting that you are legally authorised to make the contribution under the project's MIT License (see the [Developer Certificate of Origin](https://developercertificate.org/)).
23+
24+
Sign off automatically with:
25+
26+
```bash
27+
git commit -s -m "your commit message"
28+
```
29+
30+
This adds `Signed-off-by: Your Name <your@email.com>` to the commit message. A CI check enforces this on every pull request.
31+
32+
To fix unsigned commits before opening a PR:
33+
34+
```bash
35+
git rebase --signoff HEAD~<number-of-commits>
36+
```
37+
2038
## Making changes
2139

2240
1. Fork the repository and create a branch from `main`
2341
2. Make your changes
2442
3. Ensure `npm run type-check` and `npm run build` pass
2543
4. If you have a BookStack instance available, run `npm test` with the required environment variables (see below)
26-
5. Open a pull request against `main`
44+
5. Sign off all commits (see DCO section above)
45+
6. Open a pull request against `main`
2746

2847
## Running tests
2948

0 commit comments

Comments
 (0)