-
-
Notifications
You must be signed in to change notification settings - Fork 18
Migrate changelog to GitHub releases #623
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Migrate changelog to GitHub releases #623
Conversation
Co-authored-by: burak.kaya <burak.kaya@sentry.io>
|
Cursor Agent can help with this pull request. Just |
Co-authored-by: burak.kaya <burak.kaya@sentry.io>
Co-authored-by: burak.kaya <burak.kaya@sentry.io>
* Refactor: Improve changelog generation and mock fs This commit refactors the changelog generation logic to correctly handle category-level exclusions and improves the mocking of the `fs` module by using `jest.requireActual` for `readFileSync`. It also updates the `gcsAPI` tests to use the mocked `fs.existsSync`. Co-authored-by: burak.kaya <burak.kaya@sentry.io> * chore: Remove package-lock.json and regenerate yarn.lock - Remove npm-generated package-lock.json file - Regenerate yarn.lock with current dependencies - Project uses yarn as the package manager * fix: Resolve all TypeScript compilation and test failures Fixed multiple TypeScript compilation errors and dependency issues: **TypeScript Fixes:** - Fixed github.ts: Changed Promise resolve callback to match expected signature - Fixed awsLambdaLayerManager.ts: - Added Runtime import and cast CompatibleRuntimes to Runtime[] - Cast headers to Record<string, string> for fetch compatibility - Fixed registry.ts: Added explicit RemoteArtifact type to mapLimit callback - Fixed brew.ts: Added RemoteArtifact import and type annotation **Configuration Fixes:** - tsconfig.build.json: Added noImplicitUseStrict: false to override deprecated parent config option - jest.config.js: Added transformIgnorePatterns for ESM modules (dot-prop, configstore) - package.json: Pinned dot-prop to ^5.3.0 to avoid ESM-only version 10.x that breaks Jest **Test Results:** - All 38 test suites passing ✅ - 369 tests passing, 1 skipped (370 total) - 28 snapshots passing --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com>
BYK
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's great that you followed the existing changelog style but GitHub's automated release notes format is:
## <Category Title>
- <PR Title> by @<author-with> in [#<PR no>](<link to PR>)
So we need to align with that.
src/utils/changelog.ts
Outdated
| // Check label exclusions | ||
| if (exclude.labels) { | ||
| for (const excludeLabel of exclude.labels) { | ||
| if (labels.includes(excludeLabel)) { | ||
| return true; | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be cleaner with exclude.labels.some(label => labels.includes(label)). Also we may wanna convert labels to a Set() for efficient look up if this is happenning frequently.
src/utils/changelog.ts
Outdated
| // Check author exclusions | ||
| if (exclude.authors && author) { | ||
| if (exclude.authors.includes(author)) { | ||
| return true; | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Like my previous comment: probably better to make exclude.authors a Set() right after parsing
src/utils/changelog.ts
Outdated
|
|
||
| /** | ||
| * Checks if a PR is excluded at the category level | ||
| * Category-level exclusions completely remove the PR from the changelog |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is incorrect. A category level exclusion just removes the PR from that category. shouldExcludePR covers the case where a PR should be completely omitted from changelogs.
src/utils/changelog.ts
Outdated
|
|
||
| for (const category of config.changelog.categories) { | ||
| // Check if PR matches category labels | ||
| if (!category.labels || category.labels.length === 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's normalize this data right after parsing the config to either category.labels being undefined if it's an empty array or it is always an empty array if it is undefined in the actual config.
src/utils/changelog.ts
Outdated
| let matchesCategory = false; | ||
| for (const categoryLabel of category.labels) { | ||
| if (categoryLabel === '*') { | ||
| matchesCategory = true; | ||
| break; | ||
| } | ||
| if (labels.includes(categoryLabel)) { | ||
| matchesCategory = true; | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| if (!matchesCategory) { | ||
| continue; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really need to check if a PR matches a category? I mean if it is excluded, that's enough to NOT have it here. Would that not be more efficient?
src/utils/changelog.ts
Outdated
| if (categoryLabel === '*') { | ||
| matchesCategory = true; | ||
| break; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't think this logic is correct. Here's what the spec says:
Use * as a catch-all for pull requests that didn't match any of the previous categories.
That means we should check this last.
src/utils/changelog.ts
Outdated
| // Apply category-level exclusions (these completely hide the PR) | ||
| if (isCategoryLevelExcluded(labels, author, releaseConfig)) { | ||
| continue; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As mentioned earlier, this logic is incorrect. This just hides the PR from a specific category, not necessarily from everything else.
src/utils/changelog.ts
Outdated
| } | ||
|
|
||
| // Match PR to category | ||
| const categoryTitle = matchPRToCategory(labels, releaseConfig); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it makes more sense to bake the isCategoryLevelExcluded logic into matchPRToCategory so it just returns whatever category it matches the PR to, taking the exclusions into account.
src/utils/changelog.ts
Outdated
| // If we have both PR and author, add to category PRs list | ||
| // Otherwise, add to leftovers (e.g., PR without author, or commit without PR) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: you should never have a PR without an author?
src/utils/changelog.ts
Outdated
| // XXX(BYK): This case should never happen in real life | ||
| throw new Error(`Cannot get information for milestone #${milestoneNum}`); | ||
| // Generate sections for each category | ||
| for (const categoryTitle of Object.keys(categories)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mighte be better to make categories a Map()
Co-authored-by: burak.kaya <burak.kaya@sentry.io>
Co-authored-by: burak.kaya <burak.kaya@sentry.io>
src/utils/changelog.ts
Outdated
| exclude?: { | ||
| labels?: Set<string>; | ||
| authors?: Set<string>; | ||
| }; | ||
| categories?: NormalizedCategory[]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't make anything optional in normalized configs. Empty sets and arrays are easier.
src/utils/changelog.ts
Outdated
| exclude?: { | ||
| labels?: Set<string>; | ||
| authors?: Set<string>; | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above, don't make anything optional in normalized configs. Use empty sets when needed.
Co-authored-by: burak.kaya <burak.kaya@sentry.io>
Co-authored-by: burak.kaya <burak.kaya@sentry.io>
| '### Better drivetrain', | ||
| '', | ||
| 'By: @alice (#123), @bob (#456)', | ||
| '- Upgraded the manifold (#123) by @alice in [#123](https://github.com/test-owner/test-repo/pull/123)', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should strip the PR no at the end of commit logs or PR titles when they appear like this: (#<PR_NO>)
This commit refactors the changelog exclusion logic to be more concise and removes unnecessary checks. It also updates the yarn.lock file to reflect the latest dependency versions. Co-authored-by: burak.kaya <burak.kaya@sentry.io>
Co-authored-by: burak.kaya <burak.kaya@sentry.io>
Co-authored-by: burak.kaya <burak.kaya@sentry.io>
Bumps [js-yaml](https://github.com/nodeca/js-yaml) from 4.1.0 to 4.1.1. - [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md) - [Commits](nodeca/js-yaml@4.1.0...4.1.1) --- updated-dependencies: - dependency-name: js-yaml dependency-version: 4.1.1 dependency-type: direct:development ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [js-yaml](https://github.com/nodeca/js-yaml) from 3.13.1 to 4.1.1. - [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md) - [Commits](nodeca/js-yaml@3.13.1...4.1.1) --- updated-dependencies: - dependency-name: js-yaml dependency-version: 4.1.1 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* chore: Upgrade sentry/node to latest * fix
fbe8b24 to
e02c495
Compare
The older Jest version had issues with strip-ansi ESM module resolution when running on Node.js 22. Also added a resolution to pin strip-ansi in @jest/reporters to the CJS-compatible version.
Rebase artifact left 'yarn' prefix on a line in the test file.
Set.intersection() is only available in Node 22+. Use a loop to check for excluded labels instead.
0b29d66 to
0513aad
Compare
When formatting PR entries for the changelog, the PR number like '(#123)' at the end of the title is now stripped since the PR link is already included at the end of the entry.
0513aad to
79eaedc
Compare
| }; | ||
| commits[hash] = commit; | ||
|
|
||
| if (!githubCommit) { | ||
| missing.push(commit); | ||
| } | ||
| if (!commit.milestone) { | ||
|
|
||
| if (!categoryTitle) { | ||
| leftovers.push(commit); | ||
| } else { | ||
| const milestone = milestones[commit.milestone] || { | ||
| prs: [] as PullRequest[], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: normalizeReleaseConfig() crashes with TypeError if config.changelog.categories is a non-array truthy value due to missing runtime type validation.
Severity: CRITICAL | Confidence: High
🔍 Detailed Analysis
The normalizeReleaseConfig() function reads YAML configuration without runtime schema validation. If config.changelog.categories is provided as a non-array truthy value (e.g., a string or an object) in the .github/release.yml file, the if (config.changelog.categories) check on line 336 passes. However, the subsequent call to .map() on line 337 will then throw a TypeError: config.changelog.categories.map is not a function, as map is not a method on non-array types. This unhandled error will crash the changelog generation process.
💡 Suggested Fix
Add runtime validation using Array.isArray(config.changelog.categories) before attempting to call .map() on line 337. Consider implementing a more robust schema validation for the entire ReleaseConfig object to prevent similar issues.
🤖 Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.
Location: src/utils/changelog.ts#L296-L307
Potential issue: The `normalizeReleaseConfig()` function reads YAML configuration
without runtime schema validation. If `config.changelog.categories` is provided as a
non-array truthy value (e.g., a string or an object) in the `.github/release.yml` file,
the `if (config.changelog.categories)` check on line 336 passes. However, the subsequent
call to `.map()` on line 337 will then throw a `TypeError:
config.changelog.categories.map is not a function`, as `map` is not a method on
non-array types. This unhandled error will crash the changelog generation process.
Did we get this right? 👍 / 👎 to inform future reviews.
Reference ID: 3326459
Replaces the milestone-based changelog generation with a system that uses GitHub's
release.ymlcategories.This change leverages GitHub's native release notes configuration for more flexible and powerful categorization of PRs based on labels and exclusion rules, moving away from the less flexible milestone-based approach.