Skip to content

Unify update feeds with channel-aware installer manifest - #414

Merged
tonythethompson merged 2 commits into
mainfrom
unify-update-feeds-c6
Oct 9, 2026
Merged

tonythethompson merged 2 commits into
mainfrom
unify-update-feeds-c6

Conversation

@tonythethompson

@tonythethompson tonythethompson commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

C6 core half (combined-priority work-split).

  • Application.Updates.IUpdateService gains a channel-aware CheckForUpdateAsync overload with a default Stable-forwarding implementation, so existing callers and fakes compile unchanged.
  • UpdateService resolves manifest.json (Stable) vs manifest-preview.json (Preview) and ignores prerelease manifests on Stable.
  • ReleaseManifestUpdateService repointed off the dead api.trackdub.com host to releases.trackdub.ai (last api.trackdub.com reference in the repo).

Verification: UpdateServiceTests 19/19, Infrastructure.Tests 430/430, Application.Tests 1149/1149, Release -warnaserror clean on Application + Infrastructure.

Follow-ups (not in this PR): gated UpdateViewModel passes channel through after repin; release pipeline must publish manifest-preview.json.

View guided diff

Summary by CodeRabbit

  • New Features
    • Update checks now support stable and preview release channels, so preview updates can be checked separately from stable releases.
  • Bug Fixes
    • Stable-channel checks no longer offer prerelease versions as updates.
    • Update checks use the unified release feed, including when checking for preview releases.

Give Application.Updates.IUpdateService a channel-aware
CheckForUpdateAsync overload (default forwards to Stable so existing
callers and fakes compile unchanged). UpdateService resolves
manifest.json for Stable and manifest-preview.json for Preview and
ignores prerelease manifests on Stable. Repoint
ReleaseManifestUpdateService off the dead api.trackdub.com host to
releases.trackdub.ai, removing the last api.trackdub.com reference.
Covers C6 core half of the combined-priority work-split.
Copilot AI balanced review requested due to automatic review settings October 9, 2026 04:01
@cursor

cursor Bot commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

How to use the Graphite Merge Queue

Add either label to this PR to merge it via the merge queue:

  • queue - adds this PR to the back of the merge queue
  • fast - for urgent changes, fast-track this PR to the front of the merge queue

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-09T04:02:55.973325Z df1cbb6 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@coderabbitai

coderabbitai Bot commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 597cd2ec-fc8b-4771-a9ba-9592ee7284a4

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: a680b7a7-4e73-4c8f-bd64-a0368230d1ed

📥 Commits

Reviewing files that changed from the base of the PR and between 20662b8 and df1cbb6.


📒 Files selected for processing (4)
  • src/Trackdub.Application/Updates/IUpdateService.cs
  • src/Trackdub.Infrastructure/Updates/ReleaseManifestUpdateService.cs
  • src/Trackdub.Infrastructure/Updates/UpdateService.cs
  • tests/Trackdub.Infrastructure.Tests/UpdateServiceTests.cs

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.



📝 Walkthrough

Walkthrough

Update checks now accept a channel and select a stable or preview manifest. Stable checks ignore prerelease manifests. The legacy release manifest service uses the new releases.trackdub.ai URL. Tests verify channel-based requests and stable prerelease handling.

Changes

Update channels

Layer / File(s) Summary
Channel selection and prerelease handling
src/Trackdub.Application/Updates/IUpdateService.cs, src/Trackdub.Infrastructure/Updates/UpdateService.cs, tests/Trackdub.Infrastructure.Tests/UpdateServiceTests.cs
The interface adds a channel-aware overload that forwards to the existing overload by default. UpdateService selects the manifest URL by channel and ignores prerelease manifests for stable checks. Tests verify the requested URLs and stable prerelease behavior.
Legacy service manifest URL
src/Trackdub.Infrastructure/Updates/ReleaseManifestUpdateService.cs, tests/Trackdub.Infrastructure.Tests/UpdateServiceTests.cs
ReleaseManifestUpdateService uses the releases.trackdub.ai manifest URL. A test verifies that its preview-channel check requests the preview manifest.

Priority: ⬇️ Low

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

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant UpdateService
  participant ManifestEndpoint
  Caller->>UpdateService: CheckForUpdateAsync(currentVersion, channel)
  UpdateService->>ManifestEndpoint: GET manifest for selected channel
  ManifestEndpoint-->>UpdateService: Release manifest
  alt Stable channel with prerelease manifest
    UpdateService-->>Caller: No update and no error
  else Other manifest cases
    UpdateService-->>Caller: Continue version and download URL validation
  end
Loading

Merge Risk

Merge Risk: ⚪ Minimal · up to df1cb

This change adds channel-specific manifest selection and updates the legacy feed host. No concrete user-facing failure or merge-blocking risk is established; normal validation remains appropriate.

Security Architecture Review

Security architecture risk: 🔵 Low · up to df1cb

Stable remains the default, preview selection uses fixed release URLs, and existing download verification is unchanged. No introduced security defect was established. Production feed authority and the pending caller integration remain unverified, so end-to-end update safety is not yet established.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — If a caller connects manifest results to download and launch, release-feed authority can influence executable content on consuming machines. The existing Windows launch requests elevation through runas. Deployed consumer scope and production caller sequencing were not established.

Security Findings and Attack Paths

  • inferred — A party controlling a trusted manifest could choose both the installer URL and its expected checksum. SHA-256 verification checks consistency with that manifest, not independent publisher identity. This dependency predates the PR; distinct authority over the new Preview feed was not evidenced.

Trust Boundaries and Controls

  • observed — Cached and newly downloaded installer files are checksum-verified before a successful download result. Launch independently accepts an existing local path without checksum verification. The legacy manifest provider returns a URL rather than the checksum-bearing ReleaseEntry; its downstream consumer was not established. These controls and contract differences are pre-existing.

Resilience and Maintainability Implications

  • observed — Cache paths depend on version and platform, not channel or checksum, and cancellation does not consistently delete partial files. These mechanisms predate the PR. Equal-version releases share paths, but actual cross-channel replacement of a retained installer path remains conditional on unverified payloads and caller ordering.

Hardening Proposals

  • proposed — Before wiring production Preview installation, bind downloaded artifacts to immutable release identity, isolate competing downloads, and verify the selected artifact at launch. Validate publisher authority and representative production manifests for both channels. These are integration safeguards, not established PR vulnerabilities.



🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check Warning The description provides a clear summary, test results, and follow-up notes, but it omits most required template sections, including the linked issue, scope checkboxes, architecture review, license/mo… Update the description to include all template headings and required checklist items. Add the linked issue, scope confirmation, testing checklist and notes, architecture review, license/model impact, risk and rollback assessment, milestone …
Docstring Coverage Warning Docstring coverage is 5.88% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 17 functions across 4 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check Passed The title clearly summarizes the main change: unified update feeds with channel-aware installer manifests.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.

Full details: Description check

Explanation

The description provides a clear summary, test results, and follow-up notes, but it omits most required template sections, including the linked issue, scope checkboxes, architecture review, license/model impact, risk and rollback, milestone notes, and agent notes.

Resolution

Update the description to include all template headings and required checklist items. Add the linked issue, scope confirmation, testing checklist and notes, architecture review, license/model impact, risk and rollback assessment, milestone notes, and agent notes. Mark each item as applicable or not applicable.



✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR

🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

✨ Simplify code
  • Commit to this branch
  • Create a new PR

🛠️ Fix failing CI checks 💡
  • Commit to this branch
  • Create a new PR


  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@qodo-code-review

Copy link
Copy Markdown
Contributor

PR Summary by Qodo

Add channel-aware installer update manifests and unify release hosts

✨ Enhancement 🐞 Bug fix 🕐 20-40 Minutes

Grey Divider

AI Description

• Route installer update checks to Stable or Preview manifests while preserving existing callers.
• Ignore prerelease manifests on Stable and move the legacy update service to the live release host.
• Test feed selection, prerelease filtering, and the legacy service’s release URL.
Diagram

graph TD
  caller["Update callers"] --> api["IUpdateService"] --> service["Installer update service"] --> channel{"Channel?"}
  channel -->|Stable| stable["Stable manifest"] --> gate{"Prerelease?"} --> result["Update result"]
  channel -->|Preview| preview["Preview manifest"] --> result
Loading
High-Level Assessment

Keep channel selection in the installer service and preserve the old interface method for compatibility. Sharing a URL resolver with the legacy service would add an abstraction for two fixed paths with different manifest schemas. Passing the selected channel from the UI and publishing the Preview manifest remain follow-ups.

Files changed (4) +129 / -2

Enhancement (2) +30 / -1
IUpdateService.csAdd a backward-compatible channel-aware update check +12/-0

Add a backward-compatible channel-aware update check

• Adds an overload accepting UpdateChannel. Its default implementation calls the existing method, so current implementations and callers need no immediate changes.

src/Trackdub.Application/Updates/IUpdateService.cs

UpdateService.csSelect installer manifests by channel +18/-1

Select installer manifests by channel

• Preserves the existing Stable check while adding a channel-aware check that requests the Preview manifest when selected. Stable checks return no update for prerelease manifests.

src/Trackdub.Infrastructure/Updates/UpdateService.cs

Bug fix (1) +1 / -1
ReleaseManifestUpdateService.csMove the legacy manifest service to the live release host +1/-1

Move the legacy manifest service to the live release host

• Replaces the obsolete api.trackdub.com manifest URL with releases.trackdub.ai. Its existing channel-based Preview URL derivation now targets that host too.

src/Trackdub.Infrastructure/Updates/ReleaseManifestUpdateService.cs

Tests (1) +98 / -0
UpdateServiceTests.csCover channel URLs and Stable prerelease filtering +98/-0

Cover channel URLs and Stable prerelease filtering

• Adds request-URL assertions for Stable, Preview, and the legacy service, plus a Stable prerelease rejection test. The HTTP test handler now records the last request.

tests/Trackdub.Infrastructure.Tests/UpdateServiceTests.cs

@amazon-q-developer amazon-q-developer Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The implementation successfully unifies update feeds with channel-aware manifests. The changes correctly add a channel-aware overload to IUpdateService, migrate from the deprecated api.trackdub.com to releases.trackdub.ai, and implement proper prerelease filtering for the Stable channel. The comprehensive test coverage validates all the new functionality including channel routing, prerelease handling, and manifest URL resolution. All 19 UpdateServiceTests pass as noted in the PR description. No blocking issues found.


You can now have the agent implement changes and create commits directly on your pull request's source branch. Simply comment with /q followed by your request in natural language to ask the agent to make changes.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: df1cbb69df

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

return new Trackdub.Application.Updates.UpdateCheckResult(false, null, "Release manifest could not be parsed.");
}

if (channel == UpdateChannel.Stable && schema.IsPrerelease)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Parse prerelease versions in the Preview path

When the Preview manifest contains a normal SemVer prerelease such as 2.0.1-beta.1 (the format already exercised by CheckForUpdatesAsync_SemVerSuffix_ReturnsUpdateResult), this branch falls through to Version.TryParse(schema.LatestVersion), which rejects the suffix and returns “Version format in manifest is invalid.” Consequently, the newly added Preview channel cannot offer actual prerelease builds; compare prerelease-aware versions or normalize them before parsing.

Useful? React with 👍 / 👎.

@qodo-code-review

qodo-code-review Bot commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Remediation recommended

1. Preview users cannot detect beta updates ✓ Resolved
Description
UpdateService.CheckForUpdateAsync selects the preview manifest but passes its LatestVersion
directly to Version.TryParse, which rejects prerelease suffixes such as -beta.1. When a preview
manifest uses that format, the check returns a version-format error instead of an available update,
despite the legacy preview service accepting the same version.
Code

src/Trackdub.Infrastructure/Updates/UpdateService.cs[51]

+                .GetStringAsync(BuildManifestUrl(channel), cancellationToken)
Relevance

●●● Strong

Clear preview-channel correctness bug; deterministic parser fix aligns with stated channel-aware
update intent.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The added manifest request makes preview releases flow into the existing raw version parser. The
legacy service strips SemVer suffixes before parsing, and its preview test explicitly expects
2.0.1-beta.1 to be accepted.

src/Trackdub.Infrastructure/Updates/UpdateService.cs[41-73]
src/Trackdub.Infrastructure/Updates/ReleaseManifestUpdateService.cs[81-89]
tests/Trackdub.Infrastructure.Tests/UpdateServiceTests.cs[166-190]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new preview manifest route reaches version parsing that rejects SemVer prerelease suffixes, so beta releases are not detected.

## Fix Focus Areas
- src/Trackdub.Infrastructure/Updates/UpdateService.cs[51-73]
- tests/Trackdub.Infrastructure.Tests/UpdateServiceTests.cs[219-240]

## Recommended Fix
Parse and compare prerelease versions in the channel-aware update check, including an installed prerelease version. Add a preview-manifest test using a version such as `2.0.1-beta.1`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
✅ Compliance rules (platform): 4 rules
✅ Cross-repo context — repo relationships
  Explored: repo: trackdubllc/Trackdub-gated (sha: e9b9e35b) — View relationship
✅ REVIEW.md
Review mode: Auto: ⚖️ Balanced: Runtime update behavior and public API contract changes warrant careful single-pass review.

Grey Divider

Tip of the day
💡 Did you know, you can show, collapse, or hide each part of a finding: code, evidence, and all

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread src/Trackdub.Infrastructure/Updates/UpdateService.cs
@qodo-code-review

Copy link
Copy Markdown
Contributor

Qodo Fixer

No findings are within the configured fix scope. To change which findings are fixed, adjust the setting on your Qodo configuration page.

@tonythethompson tonythethompson left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

One material note on Preview version parsing; otherwise the channel URL split and Stable prerelease gate look right.

Comment on lines +60 to +64
if (channel == UpdateChannel.Stable && schema.IsPrerelease)
{
logger.LogInformation(
$"Ignoring prerelease {schema.LatestVersion} on the Stable channel.");
return new Trackdub.Application.Updates.UpdateCheckResult(false, null, null);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Version.TryParse immediately below still rejects SemVer pre-release tags (2.0.1-beta.1, 2.1.0-preview.3). Preview manifests will almost always publish those forms, so a Preview check returns "Version format in manifest is invalid" instead of an update — this Stable IsPrerelease gate never gets a chance to help on the Preview path.

ReleaseManifestUpdateService already strips -/+ suffixes before comparing (SanitizeVersion). Mirror that here (or share a helper) for both schema.LatestVersion and currentVersion, and keep the full original string on ReleaseEntry. Worth a Preview test with a suffixed latest version; the new Preview URL test uses plain 2.0.0, so this gap is unguarded.

Residual: strip-and-compare still collapses 2.0.0-beta.1 vs 2.0.0-beta.2; fine to leave unless Preview bumps often within the same numeric triple.

@opencode-agent

opencode-agent Bot commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

The discovery worker independently confirmed my analysis: no confirmed defects in the changed code. The PR is a clean, well-tested, low-risk change.

Per the skill, with no confirmed findings and no material verification notes, I report clean and do not submit an empty review.

No noteworthy issues found.

The PR cleanly adds a channel-aware CheckForUpdateAsync(string, UpdateChannel, CancellationToken) overload to Trackdub.Application.Updates.IUpdateService via a default interface method that forwards to the existing Stable overload (so FakeUpdateService and other implementers compile unchanged), and wires UpdateService to fetch manifest.json vs manifest-preview.json plus ignore prerelease manifests on the Stable channel. The default-method/concrete-override interaction is recursion-free; the BuildManifestUrl default-to-Stable fallback matches existing UpdateChannelSettings conventions; the Stable prerelease guard ordering and null-error convention are consistent with the surrounding code; and the host repoint is HTTPS-only with no trust-boundary change. The four new tests cover Stable/Preview URL routing and the Stable-prerelease-ignore path. No actionable findings to post.

github run

@tonythethompson

Copy link
Copy Markdown
Contributor Author

/q fix

@amazon-q-developer

Copy link
Copy Markdown
Contributor

I'll implement the fix for the prerelease version parsing issue:

Changes to be made:
• Add a SanitizeVersion helper method to strip SemVer prerelease suffixes (lines after - or +) in src/Trackdub.Infrastructure/Updates/UpdateService.cs
• Update version parsing in CheckForUpdateAsync to sanitize both schema.LatestVersion and currentVersion before passing to Version.TryParse in src/Trackdub.Infrastructure/Updates/UpdateService.cs:67-68
• Keep the full original version string in the ReleaseEntry object for display purposes
• Add a test case for Preview manifest with prerelease version (e.g., 2.0.1-beta.1) in tests/Trackdub.Infrastructure.Tests/UpdateServiceTests.cs

@amazon-q-developer

Copy link
Copy Markdown
Contributor

✅ Changes committed. The prerelease version parsing issue has been fixed by adding a StripVersionSuffix helper method that removes SemVer suffixes before parsing, similar to the existing ReleaseManifestUpdateService approach. Preview channel manifests can now use versions like 2.0.1-beta.1 successfully, while the full version string is preserved in the ReleaseEntry for display purposes. Added test coverage for this scenario.

Add StripVersionSuffix helper to remove SemVer prerelease suffixes
(e.g., -beta.1, -preview.3) before parsing versions, allowing Preview
channel manifests to use standard prerelease version formats. Keep
full version strings in ReleaseEntry for display purposes.

Add test coverage for Preview channel with prerelease versions.
@tonythethompson
tonythethompson merged commit 318c9da into main Oct 9, 2026
13 checks passed
@tonythethompson
tonythethompson deleted the unify-update-feeds-c6 branch October 9, 2026 11:49
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.

2 participants