chore: establish DCO enforcement with remediation workflow#84
chore: establish DCO enforcement with remediation workflow#84Sachindu-Nethmin wants to merge 3 commits intosimiligh:mainfrom
Conversation
📝 WalkthroughWalkthroughAdds DCO enforcement and remediation: a DCO config file, a GitHub Actions workflow to prompt and apply signed-off remediation commits, a PR template checklist item requiring signed commits, and CONTRIBUTING.md guidance for signing and remediation. Changes
Sequence DiagramsequenceDiagram
participant GitHub as GitHub Events
participant Workflow as DCO Remediation Workflow
participant Repo as Git Repository
participant PR as Pull Request
GitHub->>Workflow: DCO status check fails
activate Workflow
Workflow->>Workflow: Locate PR(s) for failing commit SHA
Workflow->>PR: Post sign-off prompt comment (if not posted)
deactivate Workflow
GitHub->>Workflow: issue_comment event (author replies with sign-off phrase)
activate Workflow
Workflow->>Workflow: Verify commenter is PR author
alt Authorized & non-forked PR
Workflow->>Repo: Checkout PR branch
Workflow->>Repo: Create remediation commit with sign-off
Workflow->>Repo: Push remediation commit to branch
Workflow->>PR: Post success comment
else Forked PR or Unauthorized
Workflow->>PR: Post guidance or unauthorized notice
end
deactivate Workflow
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
CONTRIBUTING.md (1)
138-141:⚠️ Potential issue | 🟡 MinorCommit example is missing the
-sflag.This example under "Pull Request Process" shows
git commit -m "feat: add awesome feature"without-s, contradicting the DCO requirement established earlier in this document and reinforced at Line 98. Contributors following this section step-by-step will produce unsigned commits.Proposed fix
2. **Make your changes** and commit with clear messages: ```bash - git commit -m "feat: add awesome feature" + git commit -s -m "feat: add awesome feature" ```🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@CONTRIBUTING.md` around lines 138 - 141, Update the commit example under "Pull Request Process" to include the DCO sign-off flag so it matches the DCO requirement; replace the example `git commit -m "feat: add awesome feature"` with the signed version `git commit -s -m "feat: add awesome feature"` so contributors following that step produce a signed commit consistent with the policy mentioned earlier.
🧹 Nitpick comments (2)
.github/workflows/dco-remediation.yml (2)
96-102:contains()allows accidental trigger from quoted text.The
contains()filter on Line 102 matches any comment containing the magic phrase — including someone quoting it in a discussion. The author-check at Line 122 prevents an actual remediation commit from a non-author, but it will still run the job, post a "not the author" comment, and consume CI minutes. Consider usinggithub.event.comment.body == '...'for an exact match, or at least trimming whitespace before comparing.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/dco-remediation.yml around lines 96 - 102, The workflow job sign-and-push uses contains(github.event.comment.body, 'I have read the DCO document and I hereby sign the DCO') which can be triggered by quoted text; change the condition to require an exact match (use github.event.comment.body == 'I have read the DCO document and I hereby sign the DCO') or compare a trimmed version of github.event.comment.body to that exact string to avoid accidental triggers, updating the if: clause accordingly so only exact signer comments start the job.
138-155: DuplicateSigned-off-bytrailer in remediation commit.The
-sflag (Line 147) automatically appends aSigned-off-bytrailer, and the commit message body (Line 153) also contains an explicitSigned-off-by:line. The resulting commit will have two identical sign-off lines. This is functionally harmless but untidy — remove one or the other.Proposed fix — drop the explicit line from the message body
git commit --allow-empty \ -s \ -m "chore: DCO remediation for $AUTHOR_NAME I have read the DCO document and I hereby sign the DCO - for all past and future contributions. - - Signed-off-by: $AUTHOR_NAME <$AUTHOR_NAME@users.noreply.github.com>" + for all past and future contributions."🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/dco-remediation.yml around lines 138 - 155, The remediation commit in the "Push remediation commit" step currently uses git commit -s while also embedding an explicit "Signed-off-by: $AUTHOR_NAME <$AUTHOR_NAME@users.noreply.github.com>" line in the commit message body, causing a duplicate sign-off; remove the explicit "Signed-off-by: ..." line from the heredoc message body (leave the -s flag) and ensure the commit message still contains the DCO statement and name but not the manual Signed-off-by trailer.
🤖 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/dco.yml:
- Around line 1-17: This file uses CRLF line endings; convert .github/dco.yml to
LF by re-saving with Unix line endings and committing the change, and add or
update your repository .gitattributes to enforce LF for YAML (e.g., set *.yml
text eol=lf) so keys like "require" and "allowRemediationCommits" remain
unchanged; after updating .gitattributes, normalize the repo (git add
--renormalize .) and recommit the normalized .yml file.
In @.github/workflows/dco-remediation.yml:
- Around line 1-5: The file header (lines containing "Author: Sachindu Nethmin"
/ "GitHub: https://github.com/Sachindu-Nethmin") currently uses CRLF endings;
convert the file to use Unix LF ("\n") line endings (re-save with LF or run a
normalization step) so the YAML uses consistent LF newlines and passes
yamllint/DCO checks.
- Around line 44-60: The step "Find associated pull requests" writes PR_NUMBERS
to GITHUB_OUTPUT using echo which breaks when PR_NUMBERS contains multiple
lines; replace the single-line echo of "pr_numbers=$PR_NUMBERS" with the
GITHUB_OUTPUT heredoc/multiline delimiter syntax so the full newline-separated
PR_NUMBERS value is preserved, e.g., write the pr_numbers field via a heredoc
into "$GITHUB_OUTPUT" and keep the existing "found=true" line (or write it after
the heredoc) so the find-pr step reliably exports the complete list.
- Around line 130-155: The workflow silently fails for forked PRs because
GITHUB_TOKEN cannot push to a contributor's fork; update the job to detect forks
(compare steps.pr.outputs.head_repo to github.repository or set an is_fork
boolean) and gate the "Checkout PR branch" and "Push remediation commit" steps
on is_fork == 'false'; for forked PRs post an explicit comment directing the
author to the manual remediation flow (or add a clear note to the existing
prompt comment) so the action does not attempt a failing git push ("Checkout PR
branch" and "Push remediation commit" are the steps to modify and the
comment/prompt area is the place to add user-facing guidance).
In `@CONTRIBUTING.md`:
- Around line 33-35: Update the fenced code block in CONTRIBUTING.md to include
a language specifier by changing the triple-backtick fence that currently
contains the sample signature to use "text" (i.e., replace ``` with ```text) so
markdownlint will recognize it as a plain text block; locate the fenced block
containing "Signed-off-by: Your Name <your.email@example.com>" and add the
specifier.
---
Outside diff comments:
In `@CONTRIBUTING.md`:
- Around line 138-141: Update the commit example under "Pull Request Process" to
include the DCO sign-off flag so it matches the DCO requirement; replace the
example `git commit -m "feat: add awesome feature"` with the signed version `git
commit -s -m "feat: add awesome feature"` so contributors following that step
produce a signed commit consistent with the policy mentioned earlier.
---
Nitpick comments:
In @.github/workflows/dco-remediation.yml:
- Around line 96-102: The workflow job sign-and-push uses
contains(github.event.comment.body, 'I have read the DCO document and I hereby
sign the DCO') which can be triggered by quoted text; change the condition to
require an exact match (use github.event.comment.body == 'I have read the DCO
document and I hereby sign the DCO') or compare a trimmed version of
github.event.comment.body to that exact string to avoid accidental triggers,
updating the if: clause accordingly so only exact signer comments start the job.
- Around line 138-155: The remediation commit in the "Push remediation commit"
step currently uses git commit -s while also embedding an explicit
"Signed-off-by: $AUTHOR_NAME <$AUTHOR_NAME@users.noreply.github.com>" line in
the commit message body, causing a duplicate sign-off; remove the explicit
"Signed-off-by: ..." line from the heredoc message body (leave the -s flag) and
ensure the commit message still contains the DCO statement and name but not the
manual Signed-off-by trailer.
| # Author: Sachindu Nethmin | ||
| # GitHub: https://github.com/Sachindu-Nethmin | ||
| # Created: 2026-02-21 | ||
| # Last Modified: 2026-02-21 | ||
|
|
||
| # DCO Bot Configuration | ||
| # Docs: https://github.com/probot/dco | ||
|
|
||
| # Require DCO sign-off on commits | ||
| require: | ||
| members: true | ||
|
|
||
| # Allow remediation commits so contributors can retroactively sign off | ||
| # without rebasing their entire PR. | ||
| allowRemediationCommits: | ||
| individual: true | ||
| thirdParty: true |
There was a problem hiding this comment.
CRLF line endings detected — use LF (\n) for consistency.
YAMLlint reports wrong newline characters (likely CRLF). Most repositories standardize on LF. If you have a .gitattributes, ensure *.yml files use LF, and re-save this file with Unix line endings.
🧰 Tools
🪛 YAMLlint (1.38.0)
[error] 1-1: wrong new line character: expected \n
(new-lines)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/dco.yml around lines 1 - 17, This file uses CRLF line endings;
convert .github/dco.yml to LF by re-saving with Unix line endings and committing
the change, and add or update your repository .gitattributes to enforce LF for
YAML (e.g., set *.yml text eol=lf) so keys like "require" and
"allowRemediationCommits" remain unchanged; after updating .gitattributes,
normalize the repo (git add --renormalize .) and recommit the normalized .yml
file.
| # Author: Sachindu Nethmin | ||
| # GitHub: https://github.com/Sachindu-Nethmin | ||
| # Created: 2026-02-21 | ||
| # Last Modified: 2026-02-21 | ||
|
|
There was a problem hiding this comment.
CRLF line endings detected — use LF (\n) for consistency.
Same as dco.yml: YAMLlint reports wrong newline characters. Re-save with Unix line endings.
🧰 Tools
🪛 YAMLlint (1.38.0)
[error] 1-1: wrong new line character: expected \n
(new-lines)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/dco-remediation.yml around lines 1 - 5, The file header
(lines containing "Author: Sachindu Nethmin" / "GitHub:
https://github.com/Sachindu-Nethmin") currently uses CRLF endings; convert the
file to use Unix LF ("\n") line endings (re-save with LF or run a normalization
step) so the YAML uses consistent LF newlines and passes yamllint/DCO checks.
| - name: Find associated pull requests | ||
| id: find-pr | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| run: | | ||
| SHA="${{ github.event.commit.sha }}" | ||
| # Find open PRs whose head SHA matches the failed commit | ||
| PR_NUMBERS=$(gh api "repos/${{ github.repository }}/pulls?state=open&per_page=100" \ | ||
| --jq "[.[] | select(.head.sha == \"$SHA\")] | .[].number") | ||
|
|
||
| if [ -z "$PR_NUMBERS" ]; then | ||
| echo "No open PRs found for SHA $SHA" | ||
| echo "found=false" >> "$GITHUB_OUTPUT" | ||
| exit 0 | ||
| fi | ||
| echo "pr_numbers=$PR_NUMBERS" >> "$GITHUB_OUTPUT" | ||
| echo "found=true" >> "$GITHUB_OUTPUT" |
There was a problem hiding this comment.
Multi-line pr_numbers output breaks GITHUB_OUTPUT format.
If multiple open PRs share the same head SHA (uncommon but possible), PR_NUMBERS will be newline-separated. Writing it with a plain echo "pr_numbers=$PR_NUMBERS" only captures the first line. Use the heredoc delimiter syntax for multi-line outputs.
Proposed fix
- echo "pr_numbers=$PR_NUMBERS" >> "$GITHUB_OUTPUT"
+ {
+ echo "pr_numbers<<EOF"
+ echo "$PR_NUMBERS"
+ echo "EOF"
+ } >> "$GITHUB_OUTPUT"📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - name: Find associated pull requests | |
| id: find-pr | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| SHA="${{ github.event.commit.sha }}" | |
| # Find open PRs whose head SHA matches the failed commit | |
| PR_NUMBERS=$(gh api "repos/${{ github.repository }}/pulls?state=open&per_page=100" \ | |
| --jq "[.[] | select(.head.sha == \"$SHA\")] | .[].number") | |
| if [ -z "$PR_NUMBERS" ]; then | |
| echo "No open PRs found for SHA $SHA" | |
| echo "found=false" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| echo "pr_numbers=$PR_NUMBERS" >> "$GITHUB_OUTPUT" | |
| echo "found=true" >> "$GITHUB_OUTPUT" | |
| - name: Find associated pull requests | |
| id: find-pr | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| SHA="${{ github.event.commit.sha }}" | |
| # Find open PRs whose head SHA matches the failed commit | |
| PR_NUMBERS=$(gh api "repos/${{ github.repository }}/pulls?state=open&per_page=100" \ | |
| --jq "[.[] | select(.head.sha == \"$SHA\")] | .[].number") | |
| if [ -z "$PR_NUMBERS" ]; then | |
| echo "No open PRs found for SHA $SHA" | |
| echo "found=false" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| { | |
| echo "pr_numbers<<EOF" | |
| echo "$PR_NUMBERS" | |
| echo "EOF" | |
| } >> "$GITHUB_OUTPUT" | |
| echo "found=true" >> "$GITHUB_OUTPUT" |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/dco-remediation.yml around lines 44 - 60, The step "Find
associated pull requests" writes PR_NUMBERS to GITHUB_OUTPUT using echo which
breaks when PR_NUMBERS contains multiple lines; replace the single-line echo of
"pr_numbers=$PR_NUMBERS" with the GITHUB_OUTPUT heredoc/multiline delimiter
syntax so the full newline-separated PR_NUMBERS value is preserved, e.g., write
the pr_numbers field via a heredoc into "$GITHUB_OUTPUT" and keep the existing
"found=true" line (or write it after the heredoc) so the find-pr step reliably
exports the complete list.
| ``` | ||
| Signed-off-by: Your Name <your.email@example.com> | ||
| ``` |
There was a problem hiding this comment.
Add a language specifier to the fenced code block.
Markdownlint flags this block for missing a language identifier. Since it's just a text sample, text works fine.
Proposed fix
-```
+```text
Signed-off-by: Your Name <your.email@example.com>
```🧰 Tools
🪛 markdownlint-cli2 (0.21.0)
[warning] 33-33: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@CONTRIBUTING.md` around lines 33 - 35, Update the fenced code block in
CONTRIBUTING.md to include a language specifier by changing the triple-backtick
fence that currently contains the sample signature to use "text" (i.e., replace
``` with ```text) so markdownlint will recognize it as a plain text block;
locate the fenced block containing "Signed-off-by: Your Name
<your.email@example.com>" and add the specifier.
11812a3 to
b8c7af8
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
CONTRIBUTING.md (1)
138-141:⚠️ Potential issue | 🟡 MinorCommit example is missing the
-sflag — inconsistent with the DCO requirement.Step 2 of the Pull Request Process shows a commit without
-s, while the new DCO section (and Contributing Code step 4) mandategit commit -s. A contributor following only this section would create unsigned commits.📝 Proposed fix
- git commit -m "feat: add awesome feature" + git commit -s -m "feat: add awesome feature"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@CONTRIBUTING.md` around lines 138 - 141, Update the commit example in Step 2 to include the DCO sign-off by changing the shown commit command (the example string "git commit -m \"feat: add awesome feature\"") to include the -s flag so it matches the DCO requirement and the Contributing Code step 4; ensure the example now demonstrates "git commit -s -m ..." (or equivalent) and keep the commit message example unchanged other than adding -s.
🧹 Nitpick comments (2)
.github/workflows/dco-remediation.yml (2)
99-102:sign-and-pushfires regardless of whether DCO actually failed.The condition only checks for the magic phrase in any PR comment — it doesn't verify that the DCO check is currently failing. This means posting the phrase on a PR with a passing DCO check pushes an unnecessary empty commit, and repeated comments push multiple remediation commits.
Consider adding a step early in
sign-and-pushthat callsgh pr checksto verify the DCO check is actually in a failing state before proceeding.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/dco-remediation.yml around lines 99 - 102, The sign-and-push job currently triggers whenever the magic DCO phrase appears in a PR comment, even if the DCO check is passing; add an early step inside the sign-and-push job (e.g., a step named "verify-dco-failing" before creating commits) that runs gh pr checks (or uses the REST Checks API) for the current PR and validates that the DCO check is in a failing state, and if it is not failing exit the job with success/skip to prevent creating any commits; ensure the step references the PR number (github.event.issue.number) and the job name sign-and-push so reviewers can find it.
27-30: Scopecontents: writetosign-and-pushonly —ask-to-signdoesn't need it.The top-level
permissionsblock grantscontents: writeto every job.ask-to-signonly reads PR data and posts a comment; granting it write access to repository contents unnecessarily expands the blast radius if that job is ever compromised.🔒 Proposed fix — per-job permissions
-permissions: - contents: write - pull-requests: write - statuses: read jobs: ask-to-sign: name: Ask Author to Sign DCO runs-on: ubuntu-latest + permissions: + pull-requests: write + statuses: read if: > ... sign-and-push: name: Push DCO Remediation Commit runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write if: > ...🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/dco-remediation.yml around lines 27 - 30, Top-level permissions currently grant contents: write to every job; change to least privilege by moving contents: write into the sign-and-push job and reducing ask-to-sign to only the permissions it needs. Specifically, remove or change the top-level "contents: write" and add per-job permissions: in the "sign-and-push" job set contents: write (and statuses: read/pull-requests: write as needed), and in the "ask-to-sign" job set contents: read (or omit if only posting PR comments) plus pull-requests: write so ask-to-sign can read PR data and post comments without write access to repo contents. Ensure the top-level permissions no longer grant contents: write to all jobs.
🤖 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-remediation.yml:
- Around line 146-163: The remediation commit currently builds the noreply
address as "$AUTHOR_NAME@users.noreply.github.com", which won't attribute
commits for modern accounts; update the "Get PR details" step to output the PR
author's numeric id (user.id) and then in the "Push remediation commit" step
build AUTHOR_EMAIL as "${{ steps.get_pr_details.outputs.user_id }}+${{
github.event.comment.user.login }}@users.noreply.github.com" (or equivalent
using the step output), set git config user.email "$AUTHOR_EMAIL" instead of the
legacy format, and remove the manual "Signed-off-by" trailer from the git commit
message since -s already appends it; ensure you still set AUTHOR_NAME for git
config user.name.
---
Outside diff comments:
In `@CONTRIBUTING.md`:
- Around line 138-141: Update the commit example in Step 2 to include the DCO
sign-off by changing the shown commit command (the example string "git commit -m
\"feat: add awesome feature\"") to include the -s flag so it matches the DCO
requirement and the Contributing Code step 4; ensure the example now
demonstrates "git commit -s -m ..." (or equivalent) and keep the commit message
example unchanged other than adding -s.
---
Duplicate comments:
In @.github/dco.yml:
- Line 1: The .github/dco.yml file currently uses CRLF line endings; re-save
that file with Unix LF endings and update the repository attributes by adding
the line *.yml text eol=lf to .gitattributes, commit both changes, then
renormalize the repo (e.g., add/commit .gitattributes and run git add
--renormalize .) so the YAMLlint warning is resolved.
In @.github/workflows/dco-remediation.yml:
- Line 1: The file uses CRLF windows line endings; convert the file containing
the header line "# Author: Sachindu Nethmin" to Unix LF line endings, re-save
with LF (not CRLF), and commit the change; ensure your editor or git autocrlf is
configured to preserve LF (e.g., set the file to use LF line endings or run a
conversion tool) so YAML lint no longer reports wrong newline characters.
- Around line 54-60: The current echo "pr_numbers=$PR_NUMBERS" truncates
multiline PR_NUMBERS; write the multi-line output using the GitHub Actions
multiline delimiter: replace the single echo with the block that writes the
delimiter, the variable, then the closing delimiter (e.g. echo "pr_numbers<<EOF"
>> "$GITHUB_OUTPUT"; printf '%s\n' "$PR_NUMBERS" >> "$GITHUB_OUTPUT"; echo "EOF"
>> "$GITHUB_OUTPUT") so that the PR_NUMBERS variable is preserved intact for
downstream use (targets: the PR_NUMBERS variable and the lines that currently
echo to GITHUB_OUTPUT).
In `@CONTRIBUTING.md`:
- Around line 33-35: Change the fenced code block that currently uses triple
backticks for the Signed-off-by line to include a language specifier (use
```text) so Markdownlint MD040 is satisfied; locate the fenced block containing
"Signed-off-by: Your Name <your.email@example.com>" and replace the opening ```
with ```text.
---
Nitpick comments:
In @.github/workflows/dco-remediation.yml:
- Around line 99-102: The sign-and-push job currently triggers whenever the
magic DCO phrase appears in a PR comment, even if the DCO check is passing; add
an early step inside the sign-and-push job (e.g., a step named
"verify-dco-failing" before creating commits) that runs gh pr checks (or uses
the REST Checks API) for the current PR and validates that the DCO check is in a
failing state, and if it is not failing exit the job with success/skip to
prevent creating any commits; ensure the step references the PR number
(github.event.issue.number) and the job name sign-and-push so reviewers can find
it.
- Around line 27-30: Top-level permissions currently grant contents: write to
every job; change to least privilege by moving contents: write into the
sign-and-push job and reducing ask-to-sign to only the permissions it needs.
Specifically, remove or change the top-level "contents: write" and add per-job
permissions: in the "sign-and-push" job set contents: write (and statuses:
read/pull-requests: write as needed), and in the "ask-to-sign" job set contents:
read (or omit if only posting PR comments) plus pull-requests: write so
ask-to-sign can read PR data and post comments without write access to repo
contents. Ensure the top-level permissions no longer grant contents: write to
all jobs.
Signed-off-by: Sachindu-Nethmin <sachindunethminweerasinghe@gmail.com>
b8c7af8 to
b69838d
Compare
🧪 E2E Test✅ Bot responded: yes Test repo → gh-simili-bot/simili-e2e-22266908839 Auto-generated by E2E pipeline |
There was a problem hiding this comment.
Pull request overview
Establishes DCO enforcement for the repository and introduces a comment-driven remediation path so contributors can retroactively sign off without rebasing, alongside documentation/template updates to guide contributors.
Changes:
- Add probot DCO configuration enabling remediation commits.
- Add a two-step GitHub Actions workflow to prompt for and (when possible) push a remediation sign-off commit.
- Update contributor documentation and PR template to require/describe DCO sign-off.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
CONTRIBUTING.md |
Documents DCO requirements and the remediation options for existing PRs. |
.github/workflows/dco-remediation.yml |
Implements status-failure prompting and author-confirmation-based remediation commit push. |
.github/dco.yml |
Configures the DCO app to enforce sign-offs and allow remediation commits. |
.github/PULL_REQUEST_TEMPLATE.md |
Adds a checklist item reminding authors to use git commit -s. |
Comments suppressed due to low confidence (3)
.github/workflows/dco-remediation.yml:60
PR_NUMBERSmay contain multiple PR numbers separated by newlines (due to thejqfilter), but writing it to$GITHUB_OUTPUTwithecho "pr_numbers=$PR_NUMBERS"will produce an invalid/multi-line output value. Normalize it to a single line (e.g., join with spaces injq) or use the multiline output syntax (name<<EOF ... EOF).
fi
echo "pr_numbers=$PR_NUMBERS" >> "$GITHUB_OUTPUT"
echo "found=true" >> "$GITHUB_OUTPUT"
.github/workflows/dco-remediation.yml:31
- This workflow calls issue comment APIs (e.g.,
repos/.../issues/.../comments) and posts PR comments, but the workflow permissions do not includeissues: write. Also,contents: writeis granted globally even though theask-to-signjob only needs to read PR/status metadata and write comments. Consider addingissues: writeand scoping permissions per job to the minimum required (e.g., onlycontents: writefor the remediation push job).
permissions:
contents: write
pull-requests: write
statuses: read
CONTRIBUTING.md:53
- The docs say to reply with the exact phrase, but the workflow trigger uses a substring match (
contains(...)). Either make the workflow require an exact match (after trimming) or relax the wording here to avoid misleading contributors.
When the DCO check fails, a bot will comment on your PR asking if you'd like to sign.
Simply reply with the following exact phrase:
> I have read the DCO document and I hereby sign the DCO
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (1)
.github/workflows/dco-remediation.yml (1)
140-146:actions/checkout@v4is a mutable tag — consider pinning to a commit SHA.A mutable tag can be moved to point to a different (potentially malicious) commit. Pinning to the full SHA (e.g.,
actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683) prevents silent tag-movement supply-chain attacks.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/dco-remediation.yml around lines 140 - 146, Replace the mutable action tag used in the "Checkout PR branch" step by pinning actions/checkout to its full commit SHA; specifically update the uses value from "actions/checkout@v4" to the canonical commit SHA for that release (e.g., actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683) so the checkout step uses an immutable reference and prevents silent tag-movement supply-chain risks.
🤖 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-remediation.yml:
- Around line 96-102: The sign-and-push job currently always creates a
remediation commit when triggered; add an idempotency guard that first checks
whether a prior remediation has already been applied (e.g., look for the
remediation commit marker comment or a specific commit message/marker) and skip
the push if found, mirroring the deduplication logic used by ask-to-sign; if a
marker exists, have the job post an "already signed" comment instead of creating
another --allow-empty commit, and ensure the check runs before any git
commit/push steps in the sign-and-push job.
- Around line 127-138: The step with id "verify" currently interpolates `${{
github.event.comment.user.login }}` and `${{ steps.pr.outputs.pr_author }}`
inline into the shell script (assigned to COMMENTER and PR_AUTHOR); change it to
pass those expressions via the step's env: block (e.g., set COMMENTER: ${{
github.event.comment.user.login }} and PR_AUTHOR: ${{ steps.pr.outputs.pr_author
}}) and then reference $COMMENTER and $PR_AUTHOR in the run script, keeping the
rest of the logic (echoing authorized=true/false to GITHUB_OUTPUT) unchanged to
avoid expression/script-injection risks.
- Around line 27-30: The permissions block in the workflow is missing the Issues
API scope; add "issues: read" to the permissions map so the GH CLI call to check
PR comments (gh api "repos/${{ github.repository }}/issues/$PR_NUM/comments")
can succeed; update the permissions section (where
contents/pull-requests/statuses are defined) to include issues: read.
In `@CONTRIBUTING.md`:
- Line 98: Update the example commit in the "Pull Request Process" section where
the example reads git commit -m "feat: add awesome feature" so it includes the
DCO sign-off flag; replace that example commit with the signed form (e.g., add
-s to the git commit invocation) to match the "Getting Started" step 4 DCO
requirement and ensure new contributors create signed commits.
---
Duplicate comments:
In @.github/dco.yml:
- Around line 1-17: The file .github/dco.yml has CRLF line endings; re-save it
with LF (\n) line endings and commit the change, and also update your repository
.gitattributes to enforce LF by adding the pattern "*.yml text eol=lf" (or
appending that entry if .gitattributes already exists) so future .yml files are
normalized; verify the change by running a linter or checking that YAMLlint no
longer flags CRLF on .github/dco.yml.
In @.github/workflows/dco-remediation.yml:
- Around line 1-5: This file contains CRLF (Windows) line endings; re-save the
file using LF line endings (Unix) so GitHub Actions and DCO checks pass—open the
file containing the header comments "Author: Sachindu Nethmin" and "GitHub:
https://github.com/Sachindu-Nethmin" and convert all CRLF (\r\n) to LF (\n)
(your editor or git config core.autocrlf=false and a re-save or dos2unix can be
used), then commit the normalized file.
- Line 59: The current single-line write echo "pr_numbers=$PR_NUMBERS" to
GITHUB_OUTPUT truncates newline-separated PRs; fix by writing PR_NUMBERS as a
multiline output using the GitHub Actions multi-line syntax: append the start
marker (echo "pr_numbers<<EOF" >> "$GITHUB_OUTPUT"), then append the full
variable content (echo "$PR_NUMBERS" >> "$GITHUB_OUTPUT"), then append the EOF
marker (echo "EOF" >> "$GITHUB_OUTPUT"); this preserves all newline-separated
entries so the later for loop that iterates over PR_NUMBERS will process every
PR.
In `@CONTRIBUTING.md`:
- Around line 33-35: Update the fenced code block in CONTRIBUTING.md that shows
the Signed-off-by example to include a language specifier (e.g., change ``` to
```text) so Markdownlint MD040 is satisfied; locate the fenced block containing
"Signed-off-by: Your Name <your.email@example.com>" and add the language token
after the opening backticks.
---
Nitpick comments:
In @.github/workflows/dco-remediation.yml:
- Around line 140-146: Replace the mutable action tag used in the "Checkout PR
branch" step by pinning actions/checkout to its full commit SHA; specifically
update the uses value from "actions/checkout@v4" to the canonical commit SHA for
that release (e.g., actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683)
so the checkout step uses an immutable reference and prevents silent
tag-movement supply-chain risks.
| permissions: | ||
| contents: write | ||
| pull-requests: write | ||
| statuses: read |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, locate and examine the workflow file
ls -la .github/workflows/dco-remediation.yml 2>/dev/null && echo "File exists" || echo "File not found"Repository: similigh/simili-bot
Length of output: 161
🏁 Script executed:
# Read the workflow file to check permissions block and the gh api call
cat -n .github/workflows/dco-remediation.yml | head -80Repository: similigh/simili-bot
Length of output: 3680
🏁 Script executed:
# Search for the specific gh api call mentioned in the review
rg 'gh api.*issues.*comments' .github/workflows/dco-remediation.yml -A 2 -B 2Repository: similigh/simili-bot
Length of output: 414
🌐 Web query:
GitHub Actions permissions issues read pull-requests endpoint documentation
💡 Result:
To “read pull requests” from a GitHub Actions workflow (e.g., call GET /repos/{owner}/{repo}/pulls with the job’s GITHUB_TOKEN), you must grant the workflow token the pull-requests: read permission in your workflow permissions: block (otherwise it may be none / too limited, depending on org/repo defaults). GitHub documents pull-requests as a first-class GITHUB_TOKEN permission you can set to read|write|none. [2]
permissions:
contents: read
pull-requests: readWhy you sometimes also need issues: read: GitHub’s REST docs note that pull requests are a type of issue, and many “PR-ish” operations (labels, assignees, milestones, etc.) are handled via Issues API endpoints, not Pulls endpoints. So if your workflow reads PR metadata via /issues/... endpoints, you’ll need issues: read too. [1]
If you’re unsure which permission an endpoint is rejecting, GitHub’s REST API can return an X-Accepted-GitHub-Permissions response header indicating the required fine-grained permissions (useful for debugging “why 403”). [3]
Sources: GitHub REST Pulls docs (PRs are issues; Pulls endpoints vs Issues endpoints) [1], GitHub Actions GITHUB_TOKEN permissions list (includes pull-requests) [2], GitHub REST overview (accepted-permissions header) [3].
Add missing issues: read permission to prevent 403 failures on comment deduplication.
The workflow calls gh api "repos/${{ github.repository }}/issues/$PR_NUM/comments" at line 70 to check for existing prompts. This endpoint is part of the Issues API and requires issues: read permission, which is separate from pull-requests. Without it, the call fails with 403, breaking the idempotency guard and risking duplicate sign-off prompts.
Proposed fix
permissions:
contents: write
+ issues: read
pull-requests: write
statuses: read🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/dco-remediation.yml around lines 27 - 30, The permissions
block in the workflow is missing the Issues API scope; add "issues: read" to the
permissions map so the GH CLI call to check PR comments (gh api "repos/${{
github.repository }}/issues/$PR_NUM/comments") can succeed; update the
permissions section (where contents/pull-requests/statuses are defined) to
include issues: read.
| sign-and-push: | ||
| name: Push DCO Remediation Commit | ||
| runs-on: ubuntu-latest | ||
| if: > | ||
| github.event_name == 'issue_comment' && | ||
| github.event.issue.pull_request && | ||
| contains(github.event.comment.body, 'I have read the DCO document and I hereby sign the DCO') |
There was a problem hiding this comment.
No idempotency guard — duplicate remediation commits on repeated trigger phrase.
If the PR author posts the trigger phrase a second time (e.g., thinking the first attempt failed), the sign-and-push job runs again and pushes another --allow-empty remediation commit. Consider checking for an existing remediation commit marker comment before proceeding (similar to the deduplication logic in ask-to-sign), or post a "already signed" comment instead of pushing again.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/dco-remediation.yml around lines 96 - 102, The
sign-and-push job currently always creates a remediation commit when triggered;
add an idempotency guard that first checks whether a prior remediation has
already been applied (e.g., look for the remediation commit marker comment or a
specific commit message/marker) and skip the push if found, mirroring the
deduplication logic used by ask-to-sign; if a marker exists, have the job post
an "already signed" comment instead of creating another --allow-empty commit,
and ensure the check runs before any git commit/push steps in the sign-and-push
job.
| - name: Verify commenter is PR author | ||
| id: verify | ||
| run: | | ||
| COMMENTER="${{ github.event.comment.user.login }}" | ||
| PR_AUTHOR="${{ steps.pr.outputs.pr_author }}" | ||
| if [ "$COMMENTER" != "$PR_AUTHOR" ]; then | ||
| echo "⚠️ Commenter ($COMMENTER) is not the PR author ($PR_AUTHOR). Skipping." | ||
| echo "authorized=false" >> "$GITHUB_OUTPUT" | ||
| else | ||
| echo "✅ Commenter is the PR author." | ||
| echo "authorized=true" >> "$GITHUB_OUTPUT" | ||
| fi |
There was a problem hiding this comment.
Script-injection antipattern: interpolate github context values via env:, not inline.
Lines 130–131 inline ${{ github.event.comment.user.login }} and ${{ steps.pr.outputs.pr_author }} directly into the shell script. As a good security practice, you should grant the GITHUB_TOKEN the least required access — the same hardening principle applies to expression injection: user-controlled context values should be passed through env: variables to prevent injection, consistent with how lines 151–152 already handle AUTHOR_NAME / AUTHOR_ID.
♻️ Proposed fix
- - name: Verify commenter is PR author
- id: verify
- run: |
- COMMENTER="${{ github.event.comment.user.login }}"
- PR_AUTHOR="${{ steps.pr.outputs.pr_author }}"
- if [ "$COMMENTER" != "$PR_AUTHOR" ]; then
+ - name: Verify commenter is PR author
+ id: verify
+ env:
+ COMMENTER: ${{ github.event.comment.user.login }}
+ PR_AUTHOR: ${{ steps.pr.outputs.pr_author }}
+ run: |
+ if [ "$COMMENTER" != "$PR_AUTHOR" ]; then🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/dco-remediation.yml around lines 127 - 138, The step with
id "verify" currently interpolates `${{ github.event.comment.user.login }}` and
`${{ steps.pr.outputs.pr_author }}` inline into the shell script (assigned to
COMMENTER and PR_AUTHOR); change it to pass those expressions via the step's
env: block (e.g., set COMMENTER: ${{ github.event.comment.user.login }} and
PR_AUTHOR: ${{ steps.pr.outputs.pr_author }}) and then reference $COMMENTER and
$PR_AUTHOR in the run script, keeping the rest of the logic (echoing
authorized=true/false to GITHUB_OUTPUT) unchanged to avoid
expression/script-injection risks.
| 2. Comment on the issue to let others know you're working on it | ||
| 3. Create a feature branch from `main` | ||
| 4. Make your changes | ||
| 4. Make your changes and commit with the `-s` flag (see [DCO](#developer-certificate-of-origin-dco)) |
There was a problem hiding this comment.
Pull Request Process example commit (line 140) is missing -s, inconsistent with the new DCO requirement.
The Getting Started step 4 (line 98) correctly links to DCO and notes the -s flag, but the commit example in the Pull Request Process section at line 140 still shows git commit -m "feat: add awesome feature" without -s. New contributors following that section step-by-step will produce unsigned commits and hit the DCO check.
📝 Proposed fix
- git commit -m "feat: add awesome feature"
+ git commit -s -m "feat: add awesome feature"📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| 4. Make your changes and commit with the `-s` flag (see [DCO](#developer-certificate-of-origin-dco)) | |
| git commit -s -m "feat: add awesome feature" |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@CONTRIBUTING.md` at line 98, Update the example commit in the "Pull Request
Process" section where the example reads git commit -m "feat: add awesome
feature" so it includes the DCO sign-off flag; replace that example commit with
the signed form (e.g., add -s to the git commit invocation) to match the
"Getting Started" step 4 DCO requirement and ensure new contributors create
signed commits.
Description
Configure DCO (Developer Certificate of Origin) enforcement with a two-step comment-based remediation workflow. This allows contributors who submitted PRs before the DCO check was enabled to retroactively sign off without requiring a rebase. Fixes #70
Type of Change
Related Issues
Relates to DCO enforcement for the project.
Changes Made
Testing
go build ./...successfullygo test ./...successfullygo vet ./...successfullyScreenshots (if applicable)
N/A — configuration and documentation changes only.
Checklist
git commit -s) — see DCOSummary by CodeRabbit
Documentation
New Features