From d3039f23581f045dc23d68e443f620081dcfd2d0 Mon Sep 17 00:00:00 2001 From: JordonPhillips Date: Thu, 24 Jul 2025 13:49:15 +0200 Subject: [PATCH 1/2] Reintroduce changelog tool automation This adds github automation to ensure that PRs contain staged changelog entries by calling the `amend` command of the changelog tool. This command will check the diff of the PR's head against the base branch. If no staged changelog entry is present, it will post a comment reminding the requester to add one and instructing them on how to do so. If a staged changelog entry is present but lacks a PR link (since it's a chicken-and-egg problem), it will post a review comment with a commitable suggestion to add the PR link. This was previously introduced, but had to be reverted after some security concerns were brought up. There were two core issues with the previous iteration: - The workflow job was given `write-all` permissions, which is well beyond the scope of what it needed. The new workflow only has write permissions to issues and pull requests, which it needs to post comments, as well as rights to read the contents of the repo. - The workflow job was checking out the PR branch and running the changelog tool from it. This is a problem because a malicious actor could modify the changelog tool to do whatever they want and it would be run without review. This is made much worse by the permissions issue above. The new workflow now checks out the base branch to run the changelog tool from. The PR's branch is checked out separately for the changelog tool to inspect. Both copies of the repo are checked out shallowly - only the `.changes` dir of the base branch is pulled and only the `.changes/next-release` dir of the pr branch is pulled. --- .github/workflows/changelog-ci.yml | 87 ++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 .github/workflows/changelog-ci.yml diff --git a/.github/workflows/changelog-ci.yml b/.github/workflows/changelog-ci.yml new file mode 100644 index 00000000000..518a84cc9de --- /dev/null +++ b/.github/workflows/changelog-ci.yml @@ -0,0 +1,87 @@ +name: changelog +on: pull_request_target +jobs: + amend: + name: "Validate staged changelogs" + runs-on: ubuntu-latest + permissions: + # Used to pull the PR and detect changes. This is needed to see + # whether the PR introduced a staged changelog entry or not as + # well as to suggest amending the changelog entry if necessary. + contents: read + + # Used to write issue comments. This is done when there is no staged + # changelog at all. The comment will include instructions on how to + # create the changelog entry. + issues: write + + # Used to write PR comments. This is done when there is a staged + # changelog introduced by the PR, but it lacks a PR link. A PR + # comment is used so that a commitable suggestion may be posted. + pull-requests: write + steps: + + # This pulls the base branch, from which we will run the changelog + # tool. Running from the base branch prevents us from picking up + # malicious changes that might be in a PR. + - name: Pull base branch + uses: actions/checkout@v4 + with: + path: base + ref: ${{ github.base_ref }} + + # Only check out the changes directory. This isn't strictly + # necessary, but it speeds up the checkout since all we care + # about is in that directory. + sparse-checkout: .changes + + # This pulls the PR's branch, from which we MUST NOT run any code. + # All we do with it is inspect the changelog entries introduced, + # if any. + - name: Pull the PR + uses: actions/checkout@v4 + with: + path: pr + ref: ${{ github.head_ref }} + repository: ${{ github.event.pull_request.head.repo.full_name }} + + # The changelog tool only needs to know about staged changelog + # entries in the PR branch, so ONLY check out those. This makes + # the checkout faster, but also makes it harder to accidentally + # run code from the PR branch. + sparse-checkout: .changes/next-release + + # This is needed so that the changelog tool can check the diff for + # newly-introduced changes by comparing its head against that of + # the base. We still won't actually run code from that copy. + - name: Fetch base from PR copy + run: | + cd pr + git fetch origin ${{ github.base_ref }} + + - name: Install Python + uses: actions/setup-python@v5 + with: + python-version-file: "base/.changes/pyproject.toml" + + - name: Install uv + uses: astral-sh/setup-uv@v6 + with: + version-file: "base/.changes/pyproject.toml" + + - name: Install changelog tool + run: | + cd base/.changes + uv sync --locked --all-extras --all-groups --dev + + - name: Run validation script + env: + GITHUB_TOKEN: ${{ github.token }} + TARGET_SHA: ${{ github.event.pull_request.head.sha }} + PR_TITLE: ${{ github.event.pull_request.title }} + run: | + cd base/.changes + uv run amend \ + --review-comment \ + --pull-request-number ${{ github.event.pull_request.number }} \ + --repository-dir ${{ github.workspace }}/pr From 013b4a4d864e1fd695518304d80dd7dab31bb73f Mon Sep 17 00:00:00 2001 From: JordonPhillips Date: Thu, 11 Sep 2025 15:52:38 +0200 Subject: [PATCH 2/2] Use env vars to pass data to scripts --- .github/workflows/changelog-ci.yml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/changelog-ci.yml b/.github/workflows/changelog-ci.yml index 518a84cc9de..b0c08d1bcc5 100644 --- a/.github/workflows/changelog-ci.yml +++ b/.github/workflows/changelog-ci.yml @@ -55,9 +55,11 @@ jobs: # newly-introduced changes by comparing its head against that of # the base. We still won't actually run code from that copy. - name: Fetch base from PR copy + env: + BASE_REF: ${{ github.base_ref }} run: | cd pr - git fetch origin ${{ github.base_ref }} + git fetch origin "$BASE_REF" - name: Install Python uses: actions/setup-python@v5 @@ -79,9 +81,11 @@ jobs: GITHUB_TOKEN: ${{ github.token }} TARGET_SHA: ${{ github.event.pull_request.head.sha }} PR_TITLE: ${{ github.event.pull_request.title }} + PR_NUMBER: ${{ github.event.pull_request.number }} + REPO_DIR: ${{ github.workspace }} run: | cd base/.changes uv run amend \ --review-comment \ - --pull-request-number ${{ github.event.pull_request.number }} \ - --repository-dir ${{ github.workspace }}/pr + --pull-request-number "$REPO_NUMBER" \ + --repository-dir "$REPO_DIR/pr"