From cbf885cba62d065d0bd44a71e9f5c70f794da6fb Mon Sep 17 00:00:00 2001 From: Paradoxbound Date: Sun, 8 Mar 2026 13:08:34 +0000 Subject: [PATCH] feat: add DCO sign-off requirement and enforcement workflow Adds a GitHub Actions DCO check that fails any PR containing commits without a 'Signed-off-by:' line, satisfying OSPS-LE-01.01. Updates CONTRIBUTING.md to document the requirement and how to comply (git commit -s / git rebase --signoff). Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/dco.yml | 48 +++++++++++++++++++++++++++++++++++++++ CONTRIBUTING.md | 21 ++++++++++++++++- 2 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/dco.yml diff --git a/.github/workflows/dco.yml b/.github/workflows/dco.yml new file mode 100644 index 0000000..fc3a69e --- /dev/null +++ b/.github/workflows/dco.yml @@ -0,0 +1,48 @@ +name: DCO Check + +on: + pull_request: + branches: [main] + +permissions: + contents: read + pull-requests: read + +jobs: + dco: + name: DCO sign-off + runs-on: ubuntu-latest + + steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@a90bcbc6539c36a85cdfeb73f7e2f433735f215b # v2.15.0 + with: + egress-policy: audit + + - name: Check all commits for Signed-off-by + uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7 + with: + script: | + const commits = await github.rest.pulls.listCommits({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: context.issue.number, + per_page: 100, + }); + + const unsigned = commits.data.filter(({ commit }) => + !commit.message.includes('Signed-off-by:') + ); + + if (unsigned.length > 0) { + const list = unsigned + .map(({ sha, commit }) => ` - ${sha.slice(0, 7)}: ${commit.message.split('\n')[0]}`) + .join('\n'); + core.setFailed( + `${unsigned.length} commit(s) missing a DCO Signed-off-by line:\n${list}\n\n` + + `Please add 'Signed-off-by: Your Name ' to each commit.\n` + + `Use 'git commit -s' to sign off automatically, or 'git rebase --signoff HEAD~N' to fix existing commits.` + ); + } else { + console.log(`All ${commits.data.length} commit(s) have a valid DCO sign-off.`); + } diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 99ef51b..1c74fc3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -17,13 +17,32 @@ npm run type-check - `packages/core/` — BookStack API client and shared types (no runtime dependencies) - `packages/stdio/` — MCP server with stdio transport +## Developer Certificate of Origin (DCO) + +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/)). + +Sign off automatically with: + +```bash +git commit -s -m "your commit message" +``` + +This adds `Signed-off-by: Your Name ` to the commit message. A CI check enforces this on every pull request. + +To fix unsigned commits before opening a PR: + +```bash +git rebase --signoff HEAD~ +``` + ## Making changes 1. Fork the repository and create a branch from `main` 2. Make your changes 3. Ensure `npm run type-check` and `npm run build` pass 4. If you have a BookStack instance available, run `npm test` with the required environment variables (see below) -5. Open a pull request against `main` +5. Sign off all commits (see DCO section above) +6. Open a pull request against `main` ## Running tests