Skip to content

Commit 550e510

Browse files
shenxianpengclaude
andcommitted
fix(pr-comments): Dependabot runs honour the permissions key, so do not skip them
Reverts the Dependabot special case: since October 2021 workflows triggered by Dependabot pull requests respect the workflow's permissions key, so a workflow that grants pull-requests: write can comment on them. Treating them as read-only would have silenced the comment exactly where it works. The README now says what is true: the token is read-only by default, the permissions key lifts that, and Actions secrets are unavailable. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018xYa7m3qup5wyN5MaXFgf6
1 parent 781a040 commit 550e510

4 files changed

Lines changed: 24 additions & 97 deletions

File tree

‎README.md‎

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -184,14 +184,14 @@ fails when a contributor did not install the hook.
184184
> [docs/fork-pr-comments.md](docs/fork-pr-comments.md) for details on how to enable
185185
> this feature for fork contributions.
186186
>
187-
> **Dependabot pull requests** are skipped the same way. GitHub runs
188-
> Dependabot-triggered `pull_request` workflows with a read-only token even
189-
> when the workflow requests `pull-requests: write`, so the permission is not
190-
> the problem: the action logs a `::warning::`, leaves the report in the job
191-
> summary, and the step still exits by the checks' result. To comment on them
192-
> too, use the [two-workflow pattern](docs/fork-pr-comments.md), or run on
193-
> `pull_request_target` for Dependabot only. Adding `dependabot[bot]` to
194-
> `ignore_authors` skips the checks for those PRs altogether.
187+
> **Dependabot pull requests** are not forks, but GitHub gives their
188+
> `pull_request` runs a read-only `GITHUB_TOKEN` by default. The `permissions`
189+
> key is honoured for them, so the `pull-requests: write` grant in the
190+
> [usage example](#usage) is enough; without it the action logs a
191+
> `::warning::` on the 403 and leaves the report in the job summary. Note that
192+
> Actions secrets are not available in Dependabot-triggered runs. Adding
193+
> `dependabot[bot]` to `ignore_authors` skips the checks for those PRs
194+
> altogether.
195195
>
196196
> Note: write-access to pull-requests requires the `pull-requests: write` permission.
197197
> See [usage example](#usage).

‎docs/fork-pr-comments.md‎

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,7 @@
22

33
When a pull request is opened from a **forked repository**, the `GITHUB_TOKEN` used by the
44
`pull_request` event has **read-only** permissions by design (GitHub security policy).
5-
This means `pr-comments: true` cannot write a comment back to the PR. Pull requests
6-
opened by **Dependabot** are in the same position: GitHub runs Dependabot-triggered
7-
`pull_request` workflows with a read-only token even though the branch lives in your own
8-
repository, so everything below applies to them too.
5+
This means `pr-comments: true` cannot write a comment back to the PR.
96

107
By default, commit-check-action handles this gracefully:
118

‎main.py‎

Lines changed: 14 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1395,26 +1395,14 @@ def is_fork_pr() -> bool:
13951395
return False
13961396

13971397

1398-
#: The actor GitHub reports for pull requests Dependabot opens.
1399-
DEPENDABOT_ACTOR = "dependabot[bot]"
1400-
1401-
14021398
def is_fork_pr_with_readonly_token() -> bool:
1403-
"""Returns True when this run's GITHUB_TOKEN cannot write to the pull request.
1399+
"""Returns True when the PR is from a fork AND the event has a read-only token.
14041400
14051401
Under the pull_request event, GITHUB_TOKEN is read-only for fork PRs.
1406-
GitHub runs Dependabot-triggered pull_request workflows with a read-only
1407-
token as well, although a Dependabot branch lives in the repository
1408-
itself, so those runs take the same path: judged by ``is_fork_pr()``
1409-
alone the action tried to comment, got a 403, and advised granting
1410-
``pull-requests: write`` — which the workflow had already done.
1411-
14121402
Under pull_request_target, GITHUB_TOKEN has the workflow's configured
1413-
permissions regardless of where, or from whom, the PR came.
1403+
permissions regardless of whether the PR is from a fork.
14141404
"""
1415-
if os.getenv("GITHUB_EVENT_NAME", "") == "pull_request_target":
1416-
return False
1417-
return is_fork_pr() or os.getenv("GITHUB_ACTOR", "") == DEPENDABOT_ACTOR
1405+
return is_fork_pr() and os.getenv("GITHUB_EVENT_NAME", "") != "pull_request_target"
14181406

14191407

14201408
def get_pr_number() -> int:
@@ -1483,28 +1471,27 @@ def add_pr_comments(results: list[ScopeResult]) -> int:
14831471
print("Skipping PR comment: not a pull request event.")
14841472
return 0
14851473

1486-
# Fork PRs and Dependabot PRs triggered by the pull_request event receive
1487-
# a read-only token; the GitHub API will always reject comment writes with
1488-
# 403. pull_request_target events always have the configured permissions.
1474+
# Fork PRs triggered by the pull_request event receive a read-only token;
1475+
# the GitHub API will always reject comment writes with 403.
1476+
# pull_request_target events always have the configured token permissions.
14891477
if is_fork_pr_with_readonly_token():
14901478
msg = (
1491-
"Skipping PR comment: GITHUB_TOKEN is read-only for this run. "
1492-
"Pull requests from forked repositories, and pull requests opened "
1493-
"by Dependabot, cannot write comments via the pull_request event. "
1479+
"Skipping PR comment: pull requests from forked repositories "
1480+
"cannot write comments via the pull_request event (GITHUB_TOKEN is "
1481+
"read-only for forks). "
14941482
"See https://github.com/commit-check/commit-check-action/blob/main/docs/fork-pr-comments.md "
1495-
"for how to enable PR comments on them."
1483+
"for how to enable PR comments on fork PRs."
14961484
)
14971485
print(f"::warning::{msg}")
14981486
if JOB_SUMMARY_ENABLED and GITHUB_STEP_SUMMARY:
14991487
with open(GITHUB_STEP_SUMMARY, "a", encoding="utf-8") as f:
15001488
f.write(
15011489
"\n---\n"
15021490
"### \u2139\ufe0f PR Comment Skipped\n\n"
1503-
"Pull requests from forked repositories, and pull requests "
1504-
"opened by Dependabot, cannot write comments using the "
1505-
"`pull_request` event because `GITHUB_TOKEN` has read-only "
1506-
"permissions.\n\n"
1507-
"> **\U0001f4a1 Tip:** To enable PR comments on them, see "
1491+
"Pull requests from forked repositories cannot write comments "
1492+
"using the `pull_request` event because `GITHUB_TOKEN` has "
1493+
"read-only permissions.\n\n"
1494+
"> **\U0001f4a1 Tip:** To enable PR comments on fork PRs, see "
15081495
"[Enabling PR Comments on Fork Pull Requests]"
15091496
"(https://github.com/commit-check/commit-check-action/blob/main/docs/fork-pr-comments.md).\n"
15101497
)

‎main_test.py‎

Lines changed: 1 addition & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1843,30 +1843,6 @@ def test_push_event_skips_comment_without_warning(self):
18431843
[line for line in printed if line.startswith("::warning")], printed
18441844
)
18451845

1846-
def test_dependabot_pr_takes_the_skip_path_and_names_dependabot(self):
1847-
with (
1848-
patch("main.PR_COMMENTS_ENABLED", True),
1849-
patch.dict(
1850-
os.environ,
1851-
{
1852-
"GITHUB_EVENT_NAME": "pull_request",
1853-
"GITHUB_ACTOR": "dependabot[bot]",
1854-
"GITHUB_REF": "refs/pull/12/merge",
1855-
},
1856-
),
1857-
patch("main.is_fork_pr", return_value=False),
1858-
patch("main.JOB_SUMMARY_ENABLED", False),
1859-
patch("main.get_pr_number") as mock_number,
1860-
patch("builtins.print") as mock_print,
1861-
):
1862-
rc = main.add_pr_comments([fail_scope()])
1863-
self.assertEqual(rc, 0)
1864-
mock_number.assert_not_called() # never reached the API
1865-
warning = mock_print.call_args_list[0][0][0]
1866-
self.assertTrue(warning.startswith("::warning::Skipping PR comment"), warning)
1867-
self.assertIn("Dependabot", warning)
1868-
self.assertNotIn("403", warning)
1869-
18701846
def test_fork_pr_skips_comment_and_warns(self):
18711847
with (
18721848
patch("main.PR_COMMENTS_ENABLED", True),
@@ -2113,40 +2089,7 @@ def test_fork_pr_with_pull_request_target_event(self):
21132089
def test_same_repo_not_fork(self):
21142090
with (
21152091
patch("main.is_fork_pr", return_value=False),
2116-
patch.dict(
2117-
os.environ,
2118-
{"GITHUB_EVENT_NAME": "pull_request", "GITHUB_ACTOR": "octocat"},
2119-
),
2120-
):
2121-
self.assertFalse(main.is_fork_pr_with_readonly_token())
2122-
2123-
def test_dependabot_pull_request_has_a_readonly_token(self):
2124-
"""A Dependabot branch is in the same repository, so is_fork_pr() is
2125-
False, yet GitHub hands its pull_request runs a read-only token. It
2126-
used to fall through to the API, take a 403, and tell the user to
2127-
grant a permission the workflow already had."""
2128-
with (
2129-
patch("main.is_fork_pr", return_value=False),
2130-
patch.dict(
2131-
os.environ,
2132-
{
2133-
"GITHUB_EVENT_NAME": "pull_request",
2134-
"GITHUB_ACTOR": "dependabot[bot]",
2135-
},
2136-
),
2137-
):
2138-
self.assertTrue(main.is_fork_pr_with_readonly_token())
2139-
2140-
def test_dependabot_pull_request_target_has_a_write_token(self):
2141-
with (
2142-
patch("main.is_fork_pr", return_value=False),
2143-
patch.dict(
2144-
os.environ,
2145-
{
2146-
"GITHUB_EVENT_NAME": "pull_request_target",
2147-
"GITHUB_ACTOR": "dependabot[bot]",
2148-
},
2149-
),
2092+
patch.dict(os.environ, {"GITHUB_EVENT_NAME": "pull_request"}),
21502093
):
21512094
self.assertFalse(main.is_fork_pr_with_readonly_token())
21522095

0 commit comments

Comments
 (0)