Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions .github/workflows/changelog-enforcement.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
name: Changelog Enforcement

on:
workflow_call:

jobs:
check-changelog:
name: Check Changelog Changes
runs-on: ubuntu-24.04
if: ${{ github.event_name == 'pull_request' }}

permissions:
contents: read
pull-requests: write

steps:
- name: Check for CHANGELOG.md modifications
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # 8.0.0
with:
script: |
const prNumber = context.payload.pull_request.number;
const prTitle = context.payload.pull_request.title;
const isChangelogPR = prTitle.startsWith('meta(changelog):');

const { data: files } = await github.rest.pulls.listFiles({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber,
per_page: 100
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing pagination allows CHANGELOG.md bypass in large PRs

Medium Severity

The listFiles call only fetches the first 100 files without handling pagination. If a PR modifies more than 100 files and CHANGELOG.md is not in the first page of results, the enforcement check will fail to detect it and allow the PR to merge without proper validation. This silently bypasses the intended changelog protection mechanism.

Fix in Cursor Fix in Web


const changelogModified = files.some(file => file.filename === 'CHANGELOG.md');

console.log(`PR Title: ${prTitle}`);
console.log(`Is Changelog PR: ${isChangelogPR}`);
console.log(`CHANGELOG.md Modified: ${changelogModified}`);

if (changelogModified && !isChangelogPR) {
const commentBody = `## :warning: Manual Changelog Changes Detected

This PR modifies \`CHANGELOG.md\`, but the PR title does not start with \`meta(changelog):\`.

**Changelogs in this repository are generated automatically during releases.** Manual edits to \`CHANGELOG.md\` are not allowed in regular PRs.

### What to do:

1. **If this change is intentional**: Create a separate PR with a title starting with \`meta(changelog):\` to make changelog edits.

2. **If this was unintentional**: Remove the \`CHANGELOG.md\` changes from this PR.`;

// Avoid posting duplicate comments on re-runs
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing pagination may cause duplicate warning comments

Low Severity

The listComments call doesn't specify per_page, using the default of 30. If a PR has more than 30 comments, the existing bot comment may not be found when checking for duplicates, causing repeated warning comments to be posted on subsequent workflow runs.

Fix in Cursor Fix in Web


const botComment = comments.find(comment =>
comment.user.type === 'Bot' &&
comment.body.includes('Manual Changelog Changes Detected')
);

if (!botComment) {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body: commentBody
});
console.log('Posted comment explaining changelog policy');
} else {
console.log('Comment already exists, skipping');
}

core.setFailed('CHANGELOG.md changes are not allowed unless PR title starts with "meta(changelog):"');
} else if (changelogModified && isChangelogPR) {
console.log('CHANGELOG.md changes allowed in meta(changelog): PR');
} else {
console.log('No CHANGELOG.md changes detected');
}
9 changes: 7 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,23 @@ jobs:
name: Test Swift
uses: ./.github/workflows/swift-test.yml

changelog:
name: Changelog
uses: ./.github/workflows/changelog-enforcement.yml

required:
name: Check required jobs
runs-on: ubuntu-24.04
needs: [lint, test, test_node, test_swift]
needs: [lint, test, test_node, test_swift, changelog]
if: always()
steps:
- name: Check for failure
if: ${{
needs.lint.result != 'success' ||
needs.test.result != 'success' ||
needs.test_node.result != 'success' ||
needs.test_swift.result != 'success'
needs.test_swift.result != 'success' ||
(needs.changelog.result != 'success' && needs.changelog.result != 'skipped')
}}
run: |
echo "One or more jobs failed"
Expand Down