Skip to content

ci: check the changelog without checking out fork code - #1918

Open
Jahongir-Qurbonov wants to merge 1 commit into
aiogram:dev-3.xfrom
Jahongir-Qurbonov:ci/changelog-check-without-fork-checkout
Open

Jahongir-Qurbonov wants to merge 1 commit into
aiogram:dev-3.xfrom
Jahongir-Qurbonov:ci/changelog-check-without-fork-checkout

Conversation

@Jahongir-Qurbonov

Copy link
Copy Markdown

Description

The changelog check currently fails on every pull request opened from a fork, regardless of whether a
newsfragment was added. actions/checkout now refuses to check out fork code from a
pull_request_target workflow:

Refusing to check out fork pull request code from a 'pull_request_target' workflow. This workflow runs
with the base repository's GITHUB_TOKEN, secrets, default-branch cache scope, and runner access.
Fetching and executing a fork's code in that trusted context commonly leads to 'pwn request'
vulnerabilities.

Because the checkout step fails, towncrier check never runs, and the if: failure() step posts the
"Changelog is required!" comment even when the fragment is there. Recent examples: #1917 (has
CHANGES/1876.bugfix.rst) and #1916.

Fix

The workflow keeps running on pull_request_target, since commenting on fork pull requests needs a
token with write access, but it no longer checks out the fork:

  • only the base repository is checked out, so the code that runs is always trusted;
  • the list of changed files comes from gh api repos/{repo}/pulls/{number}/files;
  • .github/scripts/check_changelog.py applies the same rules as towncrier check, reading the
    towncrier configuration (fragment directory, news file, categories) from the base repository's
    pyproject.toml, so the categories stay in one place;
  • explicit least-privilege permissions are added (contents: read, pull-requests: write).

The pip install -U towncrier step goes away with it, so the job no longer depends on whatever
towncrier release is current.

The bot comment steps are unchanged.

Behaviour

The script matches towncrier check on the cases that matter:

changed files result
code +CHANGES/1876.bugfix.rst pass
code only fail
CHANGES.rst (release build) pass, checks skipped
CHANGES/.template.rst.jinja2 only fail
CHANGES/1234.bugfixes.rst (typo in category) fail
CHANGES/+orphan.misc.rst pass
nothing pass

Note

pull_request_target workflows run from the base branch, so this pull request will itself be checked by
the current, broken version of the workflow and its changes-required check will fail the same way.
The fix only takes effect once it is merged into dev-3.x.

Alternatives considered

  • allow-unsafe-pr-checkout: true on the checkout step restores the old behaviour in one line, but it
    opts back into exactly the risk the guard describes: towncrier would read the fork's pyproject.toml
    and jinja2 template in a job holding the base repository's token.
  • Splitting into a pull_request job plus a workflow_run job that comments is the other standard
    pattern, but it is a much larger change for the same outcome.

🤖 Generated with Claude Code

The changelog check fails on every pull request from a fork, whether or not a
newsfragment was added: `actions/checkout` refuses to check out fork code from a
`pull_request_target` workflow, so `towncrier check` never runs and the
`if: failure()` step posts the "Changelog is required!" comment anyway.

Keep the workflow on `pull_request_target`, since commenting on fork pull
requests needs a token with write access, but stop checking out the fork. Only
the base repository is checked out, the list of changed files comes from the
API, and `.github/scripts/check_changelog.py` applies the same rules as
`towncrier check`, reading the fragment directory, news file and categories
from the base repository's `pyproject.toml`.

Also drop the `pip install -U towncrier` step, so the job no longer depends on
whichever towncrier release is current, and declare least-privilege permissions.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

❌ Changelog is required!

You need to add a brief description of the changes to the CHANGES directory.

Changes file should be named like <issue or PR number>.<category>.rst,
example 1234.bugfix.rst where 1234 is the PR or issue number and bugfix is the category.

The content of the file should be a brief description of the changes in
the PR in the format of a description of what has been done.

Possible categories are: feature, bugfix, doc, removal and misc.

@github-actions github-actions Bot added the 3.x Issue or PR for stable 3.x version label Sep 22, 2026
@Olegt0rr

Copy link
Copy Markdown
Contributor

Duplicate of #1884 and #1908

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

3.x Issue or PR for stable 3.x version

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants