Skip to content

fix(release): exclude upstream commits from community contributors - #125

Merged
DevFlex-AI merged 2 commits into
devfrom
changelog-upstream
Aug 1, 2026
Merged

fix(release): exclude upstream commits from community contributors#125
DevFlex-AI merged 2 commits into
devfrom
changelog-upstream

Conversation

@DevFlex-AI

@DevFlex-AI DevFlex-AI commented Aug 1, 2026

Copy link
Copy Markdown

Issue for this PR

Closes #124

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

The v1.20.2 draft notes thanked upstream OpenCode authors (@fwang, @OpeOginni) as bolt-cli community contributors, including a raw Merge branch 'dev' of github.com:anomalyco/opencode into dev line. Those commits entered through the upstream sync merge (PR #120 by pull[bot]), not through contributions to this repo: contributors() in script/raw-changelog.ts walks every commit in the compare range with no filtering on merge commits or where the commit came from.

The fix skips merge commits (compare API parent count) and only credits a commit when a PR in this repo was authored by the commit author:

async function authored(sha: string, login: string) {
  const data = await $`gh api "/repos/${repo}/commits/${sha}/pulls"`.json()
  return (data as { user: { login: string }; base: { repo: { full_name: string } } }[]).some(
    (pr) =>
      pr.base.repo.full_name.toLowerCase() === repo.toLowerCase() &&
      pr.user.login.toLowerCase() === login.toLowerCase(),
  )
}

Upstream commits only associate with the sync PR (authored by pull[bot] or a team member), so they fail the check; a genuine community PR into this repo passes because its PR author is the contributor. Verified against real API data: upstream f67e80c associates with anomalyco#39842 (OpeOginni) and bolt-cli#120 (pull[bot]) so it is excluded, while in-repo commits associate with their own PR.

How did you verify your code works?

Ran bun script/raw-changelog.ts --from 1.20.1 --to HEAD before and after: before reproduces the v1.20.2 draft's bogus "Thank you to 2 community contributors" section; after, the section is gone while the Desktop and SDK entries are unchanged.

Screenshots / recordings

Not a UI change.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

View with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is enabled.

Summary by CodeRabbit

  • Bug Fixes
    • Improved changelog contributor attribution by excluding merge commits.
    • Contributor recognition now requires verified pull-request authorship in the configured repository.
    • Changelog entries now include commit parent information for more accurate history tracking.
    • These improvements provide more reliable contributor information and commit-history details in generated changelogs.

@vercel

vercel Bot commented Aug 1, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
bolt-cli-app Ready Ready Preview Aug 1, 2026 4:54pm

@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7fcfdab1-3535-4607-b78f-035314421408

📥 Commits

Reviewing files that changed from the base of the PR and between 79fc879 and 6165f42.

📒 Files selected for processing (1)
  • script/raw-changelog.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • script/raw-changelog.ts

📝 Walkthrough

Walkthrough

The changelog script now records commit parent counts, checks associated pull requests for repository and author matches, and excludes merge commits or commits without matching pull-request authorship from contributor collection.

Changes

Contributor attribution filtering

Layer / File(s) Summary
Commit and pull-request attribution checks
script/raw-changelog.ts
The comparison response includes commit parent counts. Contributor collection excludes merge commits and commits without an associated pull request in the configured repository authored by the commit author.

Estimated code review effort: 2 (Simple) | ~10 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes excluding upstream commits from community contributor attribution.
Description check ✅ Passed The description includes the issue, change type, implementation details, verification steps, and checklist completion.
Linked Issues check ✅ Passed The changes satisfy issue #124 by skipping merge commits and validating same-repository pull-request authorship.
Out of Scope Changes check ✅ Passed The changes are limited to contributor filtering in script/raw-changelog.ts and match issue #124.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch changelog-upstream

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed. For unrecoverable errors, disable the tool in CodeRabbit configuration.


Comment @coderabbitai help to get the list of available commands.

@deepsource-io

deepsource-io Bot commented Aug 1, 2026

Copy link
Copy Markdown

DeepSource Code Review

We reviewed changes in 8cff5cd...6165f42 on this pull request. Below is the summary for the review, and you can see the individual issues we found as inline review comments.

See full review on DeepSource ↗

Important

Some issues found as part of this review are outside of the diff in this pull request and aren't shown in the inline review comments due to GitHub's API limitations. You can see those issues on the DeepSource dashboard.

PR Report Card

Overall Grade  

Focus Area: Reliability
Security  

Reliability  

Complexity  

Hygiene  

Code Review Summary

Analyzer Status Updated (UTC) Details
JavaScript Aug 1, 2026 4:53p.m. Review ↗
Shell Aug 1, 2026 4:53p.m. Review ↗
Secrets Aug 1, 2026 4:53p.m. Review ↗
Docker Aug 1, 2026 4:53p.m. Review ↗
Python Aug 1, 2026 4:53p.m. Review ↗
CSS Aug 1, 2026 4:53p.m. Review ↗
Rust Aug 1, 2026 4:53p.m. Review ↗
Ruby Aug 1, 2026 4:53p.m. Review ↗
Swift Aug 1, 2026 4:53p.m. Review ↗
PHP Aug 1, 2026 4:53p.m. Review ↗
Lua Aug 1, 2026 4:53p.m. Review ↗
Java Aug 1, 2026 4:53p.m. Review ↗
Go Aug 1, 2026 4:53p.m. Review ↗
C & C++ Aug 1, 2026 4:53p.m. Review ↗
Ansible Aug 1, 2026 4:53p.m. Review ↗
Apex Aug 1, 2026 4:53p.m. Review ↗
Elixir Aug 1, 2026 4:53p.m. Review ↗
Groovy Aug 1, 2026 4:53p.m. Review ↗
Objective-C Aug 1, 2026 4:53p.m. Review ↗
PowerShell Aug 1, 2026 4:53p.m. Review ↗
Terraform Aug 1, 2026 4:53p.m. Review ↗
VB.NET Aug 1, 2026 4:53p.m. Review ↗
SQL Aug 1, 2026 4:53p.m. Review ↗
Scala Aug 1, 2026 4:53p.m. Review ↗
Perl Aug 1, 2026 4:53p.m. Review ↗
Kotlin Aug 1, 2026 4:53p.m. Review ↗
Helm Aug 1, 2026 4:53p.m. Review ↗
Erlang Aug 1, 2026 4:53p.m. Review ↗
Dart Aug 1, 2026 4:53p.m. Review ↗
C# Aug 1, 2026 4:53p.m. Review ↗

Important

AI Review is run only on demand for your team. We're only showing results of static analysis review right now. To trigger AI Review, comment @deepsourcebot review on this thread.

Comment thread script/raw-changelog.ts
Comment on lines +173 to +180
async function authored(sha: string, login: string) {
const data = await $`gh api "/repos/${repo}/commits/${sha}/pulls"`.json()
return (data as { user: { login: string }; base: { repo: { full_name: string } } }[]).some(
(pr) =>
pr.base.repo.full_name.toLowerCase() === repo.toLowerCase() &&
pr.user.login.toLowerCase() === login.toLowerCase(),
)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Unexpected function declaration in the global scope, wrap in an IIFE for a local variable, assign as global property for a global variable


It is considered a best practice to avoid 'polluting' the global scope with variables that are intended to be local to the script. Global variables created from a script can produce name collisions with global variables created from another script, which will usually lead to runtime errors or unexpected behavior. It is mostly useful for browser scripts.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This is a Bun ES module script, so the top-level function declaration is module-scoped, not global; the IIFE suggestion applies to classic browser scripts and every other helper in this file is declared the same way.

Comment thread script/raw-changelog.ts
)
}

async function contributors(from: string, to: string) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

`contributors` has a cyclomatic complexity of 9 with "medium" risk


A function with high cyclomatic complexity can be hard to understand and
maintain. Cyclomatic complexity is a software metric that measures the number of
independent paths through a function. A higher cyclomatic complexity indicates
that the function has more decision points and is more complex.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
script/raw-changelog.ts (2)

192-193: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add regression coverage for contributor attribution.

Cover these cases:

  • Merge commit: excluded.
  • One-parent commit with a matching PR author: included.
  • PR authored by another user: excluded.
  • PR targeting another repository or no associated PR: excluded.

Use mocked GitHub responses or a fixture-based changelog test.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@script/raw-changelog.ts` around lines 192 - 193, Add regression coverage
around the changelog filtering flow containing the parents check and authored
call. Test that merge commits are excluded, one-parent commits with matching PR
authors are included, commits authored by another user are excluded, and commits
whose PR targets another repository or has no associated PR are excluded, using
mocked GitHub responses or a changelog fixture.

192-193: 🚀 Performance & Scalability | 🔵 Trivial | 🏗️ Heavy lift

Bound per-commit GitHub lookups.

When a release range contains many eligible commits, this loop starts one sequential gh api request per commit. Use bounded concurrency or a batched query, with explicit rate-limit and failure handling.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@script/raw-changelog.ts` around lines 192 - 193, Update the commit-processing
loop around authored to avoid one sequential GitHub lookup per eligible commit
by using bounded concurrency or batched queries. Add explicit handling for
GitHub rate-limit responses and request failures, while preserving the existing
parent-count and authorship filtering behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@script/raw-changelog.ts`:
- Around line 174-175: Update the pull-request lookup around the gh api call to
request per_page=100 with --paginate, then flatten the paginated response before
applying .some(...). Preserve the existing matching predicate and return
behavior while ensuring pull requests from every page are checked.

---

Nitpick comments:
In `@script/raw-changelog.ts`:
- Around line 192-193: Add regression coverage around the changelog filtering
flow containing the parents check and authored call. Test that merge commits are
excluded, one-parent commits with matching PR authors are included, commits
authored by another user are excluded, and commits whose PR targets another
repository or has no associated PR are excluded, using mocked GitHub responses
or a changelog fixture.
- Around line 192-193: Update the commit-processing loop around authored to
avoid one sequential GitHub lookup per eligible commit by using bounded
concurrency or batched queries. Add explicit handling for GitHub rate-limit
responses and request failures, while preserving the existing parent-count and
authorship filtering behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d902501f-c985-41e7-a7f2-1fa334021f45

📥 Commits

Reviewing files that changed from the base of the PR and between 8cff5cd and 79fc879.

📒 Files selected for processing (1)
  • script/raw-changelog.ts

Comment thread script/raw-changelog.ts Outdated
Co-authored-by: Codesmith <codesmith-bot@users.noreply.github.com>
Comment thread script/raw-changelog.ts
Comment on lines +173 to +182
async function authored(sha: string, login: string) {
const data = await $`gh api --paginate --slurp "/repos/${repo}/commits/${sha}/pulls?per_page=100"`.json()
return (data as { user: { login: string }; base: { repo: { full_name: string } } }[][])
.flat()
.some(
(pr) =>
pr.base.repo.full_name.toLowerCase() === repo.toLowerCase() &&
pr.user.login.toLowerCase() === login.toLowerCase(),
)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Unexpected function declaration in the global scope, wrap in an IIFE for a local variable, assign as global property for a global variable


It is considered a best practice to avoid 'polluting' the global scope with variables that are intended to be local to the script. Global variables created from a script can produce name collisions with global variables created from another script, which will usually lead to runtime errors or unexpected behavior. It is mostly useful for browser scripts.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This is a Bun ES module script, so the top-level function declaration is module-scoped, not global; the IIFE suggestion applies to classic browser scripts and all other helpers in this file follow the same pattern.

@DevFlex-AI
DevFlex-AI merged commit 5c7d58d into dev Aug 1, 2026
43 of 46 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Release notes credit upstream commits as community contributions

1 participant