Skip to content

Include app version in GitHub PR poller User-Agent - #10046

Open
joshfree wants to merge 2 commits into
manaflow-ai:mainfrom
joshfree:fix/pr-poller-user-agent-version
Open

Include app version in GitHub PR poller User-Agent#10046
joshfree wants to merge 2 commits into
manaflow-ai:mainfrom
joshfree:fix/pr-poller-user-agent-version

Conversation

@joshfree

@joshfree joshfree commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Summary

The GitHub pull-request poller sends a fixed User-Agent of cmux-workspace-pr-poller with no version, so requests from different cmux releases are indistinguishable server-side. That makes it hard to attribute request behavior — including conditional-request (If-None-Match / ETag) revalidation and rate-limit usage — to a specific release.

This change appends the app version to the header, formatted as cmux-workspace-pr-poller/<CFBundleShortVersionString>:

  • The version is resolved once from the host app bundle's CFBundleShortVersionString, so it always reflects the shipped release with no manual update required.
  • The existing product token cmux-workspace-pr-poller is preserved as the leading component, so any server-side matching on it keeps working.
  • A /unknown fallback preserves the Product/Version shape when a version isn't available (e.g. under swift test, where Bundle.main is the test runner).
  • Formatting is factored into a small pure helper userAgentValue(appVersion:) so it can be unit-tested without depending on the bundle.

Closes #10044

Testing

Added swift-testing cases in GitHubPullRequestRequestTests.swift:

  • userAgentValueAppendsAppVersion — version appended as cmux-workspace-pr-poller/1.2.3.
  • userAgentValueTrimsSurroundingWhitespace — surrounding whitespace trimmed.
  • userAgentValueFallsBackWhenVersionMissingnil and blank both fall back to /unknown.
  • pollerRequestSendsProductTokenUserAgent — the outgoing request's User-Agent starts with cmux-workspace-pr-poller/.

Note: this change was authored on a non-macOS machine, so it was not built/run locally (cmux's Swift/Xcode toolchain is macOS-only). CI is authoritative for build + tests here.

Demo Video

N/A — no user-facing UI or behavior change (outbound request header metadata only).

Review Trigger

@codex review
@coderabbitai review
@greptile-apps review
@cubic-dev-ai review

Checklist

  • I tested the change locally (not possible on a non-macOS machine; relying on CI)
  • I added tests
  • I updated docs / changelog (no user-facing docs affected)
  • I requested bot reviews
  • I resolved bot comments
  • I resolved human comments

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


Summary by cubic

Includes the app version in the GitHub PR poller’s User-Agent to attribute request behavior by release. Previously we sent "cmux-workspace-pr-poller"; now we send "cmux-workspace-pr-poller/", falling back to "/unknown" when the version is unavailable.

  • Builds the value once from CFBundleShortVersionString via userAgentValue(appVersion:); no manual bumps.
  • Sets a static userAgentHeaderValue in GitHubPullRequestRequestCoordinator; keeps the product token first; request semantics are unchanged.
  • Tests verify formatting and whitespace trimming, the /unknown fallback, and assert the full User-Agent equals the value from userAgentValue(appVersion:) (not just the prefix).

Written for commit 1542e6d. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • Improvements
    • GitHub pull-request requests now identify the app with its current version.
    • Requests use a fallback identifier when the app version is unavailable.

The pull-request poller sent a fixed `User-Agent` of
`cmux-workspace-pr-poller` with no version, so requests from different
cmux releases were indistinguishable server-side. That makes it hard to
attribute request behavior — including conditional-request
(`If-None-Match` / ETag) revalidation and rate-limit usage — to a
specific release.

Append the app version to the header, formatted as
`cmux-workspace-pr-poller/<CFBundleShortVersionString>`. The version is
read at load time from the host app bundle, so it always reflects the
shipped release with no manual update; the product token is kept as the
leading component so existing server-side matching on it still works, and
a `/unknown` fallback preserves the `Product/Version` shape when the
version is unavailable. Formatting is factored into a testable helper.

Closes manaflow-ai#10044

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 4959e1f9-f8e6-4e97-a487-f395a0123c79
@cursor

cursor Bot commented Aug 12, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 3415a76e-03b2-4248-abc4-a0517824f567

📥 Commits

Reviewing files that changed from the base of the PR and between bd245d3 and 1542e6d.

📒 Files selected for processing (1)
  • Packages/macOS/CmuxGit/Tests/CmuxGitTests/GitHubPullRequestRequestTests.swift

📝 Walkthrough

Walkthrough

The GitHub PR poller now sends a versioned User-Agent derived from the app bundle. Missing or blank versions use unknown. Unit and request-level tests cover formatting and header transmission.

Changes

GitHub User-Agent

Layer / File(s) Summary
User-Agent construction
Packages/macOS/CmuxGit/Sources/CmuxGit/Probe/GitHubPullRequestRequestCoordinator.swift, Packages/macOS/CmuxGit/Tests/CmuxGitTests/GitHubPullRequestRequestTests.swift
The coordinator builds a Product/Version value from the bundle version and falls back to Product/unknown. Unit tests cover version formatting and fallback cases.
Request header wiring
Packages/macOS/CmuxGit/Sources/CmuxGit/Probe/GitHubPullRequestRequestCoordinator.swift, Packages/macOS/CmuxGit/Tests/CmuxGitTests/GitHubPullRequestRequestTests.swift
GitHub requests use the generated User-Agent. An asynchronous test checks the captured header prefix.

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

Suggested reviewers: austinywang

🚥 Pre-merge checks | ✅ 24 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (24 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The implementation meets issue #10044 by adding the bundle version, preserving the product token, and using an unknown fallback with tests.
Out of Scope Changes check ✅ Passed The source and test changes are limited to versioning the GitHub PR poller User-Agent and validating the related behavior.
Cmux Swift Actor Isolation ✅ Passed Production diff adds immutable User-Agent values and a pure helper inside the existing actor; it adds no MainActor models/protocols, shared mutable Sendable references, or UI background access.
Cmux Swift Blocking Runtime ✅ Passed The PR adds only User-Agent formatting/header code and deterministic tests; the production diff introduces no semaphore, wait, sleep, delayed dispatch, polling loop, sync queue, or manual lock.
Cmux Browser Automation Off-Main ✅ Passed The PR diff changes only GitHub pull-request User-Agent code and tests; it changes no browser automation, socket-worker policy, WebKit, AppKit, or processV2Command paths.
Cmux Expensive Synchronous Load ✅ Passed The production diff only adds cached User-Agent formatting from Bundle.main and replaces the header value; it adds no agent-history loader, large-file parsing, scan, or interactive main-actor path.
Cmux Cache Substitution Correctness ✅ Passed The diff only versions an outbound GitHub User-Agent; no fresh read was replaced in a persistence, history, undo, or snapshot path, and the existing ETag cache is unchanged.
Cmux No Hacky Sleeps ✅ Passed PASS: The PR diff changes only Swift source and tests, adds no sleeps, timers, or wall-clock waits, and the rule explicitly excludes Swift.
Cmux Algorithmic Complexity ✅ Passed The production diff adds one bundle-version lookup and constant-time header formatting; it introduces no scalable collection scan, nested scan, sort, filter, or batch algorithm.
Cmux Swift Concurrency ✅ Passed The diff adds only synchronous bundle/string formatting and a header assignment; added Swift lines introduce no DispatchQueue, Combine, completion-handler, or fire-and-forget Task patterns.
Cmux Swift @Concurrent ✅ Passed The PR adds only synchronous User-Agent formatting and a header value; it changes no async isolation, @concurrent annotations, or heavy-work call sites. Existing actor network methods remain unchan...
Cmux Swift Package Boundaries ✅ Passed The production diff stays in the existing CmuxGit SwiftPM target, with tests in CmuxGitTests; it introduces no independently testable logic under the app target's root Sources/ path.
Cmux Swiftpm Lockfiles ✅ Passed The PR range changes only CmuxGit Swift source and tests. It changes no Package.swift dependencies, Package.resolved, .gitignore, workflow, or Xcode project package references.
Cmux Swift Logging ✅ Passed The PR diff adds a versioned User-Agent and tests only; it adds no print, debugPrint, dump, NSLog, file logging, Logger, or sensitive diagnostic logging.
Cmux User-Facing Error Privacy ✅ Passed The diff changes only an outbound GitHub User-Agent and adds tests; it introduces no user-facing error, alert, command output, API error body, or recovery text.
Cmux Full Internationalization ✅ Passed The diff changes only GitHub User-Agent protocol metadata and tests; its literal product/version tokens are allowed, and no user-facing UI, catalog, or web locale files changed.
Cmux Swiftui State Layout ✅ Passed The PR changes only a CmuxGit actor and its tests; the diff adds no SwiftUI views, state wrappers, GeometryReader, lazy/list rows, or render-time state mutation.
Cmux Architecture Rethink ✅ Passed The diff only adds immutable User-Agent formatting and a local request-header assignment with unit/integration tests; it adds no timing, mutable state owner, observer, side channel, or UI lifecycle...
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed The PR changes only GitHub request User-Agent code and tests; the exact diff adds no NSWindow, NSPanel, NSWindowController, Window, or WindowGroup code.
Cmux Source Artifacts ✅ Passed The PR changes only a Swift source file and its Swift test file; both are intentional source/test paths, with no logs, caches, build output, scratch directories, or copied artifacts.
Cmux No Test Or Debug Seam In Production Source ✅ Passed The diff adds no test/debug seam: userAgentValue is production formatting logic used by userAgentHeaderValue and the request path, with no DEBUG/test guard or seam-style name.
Cmux No Ambient Global State ✅ Passed The diff adds static-let constants and one static helper to the existing constructable coordinator; it adds no top-level API, mutable global, static-only namespace, or singleton.
Title check ✅ Passed The title clearly and concisely describes the primary change: adding the app version to the GitHub PR poller User-Agent.
Description check ✅ Passed The description explains what changed and why, documents testing and limitations, includes the required sections, and records relevant checklist status.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@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

🤖 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
`@Packages/macOS/CmuxGit/Tests/CmuxGitTests/GitHubPullRequestRequestTests.swift`:
- Around line 449-461: Update pollerRequestSendsProductTokenUserAgent to assert
the complete User-Agent value rather than only its prefix. Derive the expected
versioned value from CFBundleShortVersionString through
userAgentValue(appVersion:), or inject a deterministic known version, and
compare it with the captured header using equality.
🪄 Autofix

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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 02a68005-018c-4da9-825b-44de39c96bd2

📥 Commits

Reviewing files that changed from the base of the PR and between b17c260 and bd245d3.

📒 Files selected for processing (2)
  • Packages/macOS/CmuxGit/Sources/CmuxGit/Probe/GitHubPullRequestRequestCoordinator.swift
  • Packages/macOS/CmuxGit/Tests/CmuxGitTests/GitHubPullRequestRequestTests.swift

The integration test previously only checked the `User-Agent` prefix, so
it would pass even if the version suffix were wrong. Compute the expected
value from the same bundle version via `userAgentValue(appVersion:)` and
assert the full header equals it, while keeping the prefix check.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 4959e1f9-f8e6-4e97-a487-f395a0123c79
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.

GitHub PR poller User-Agent omits app version

1 participant