Skip to content

refactor(release): readonly-domain-types (stack 9/12, re-split #307) - #382

Closed
YosefHayim wants to merge 1 commit into
refactor/types/readonly-stack-08-configfrom
refactor/types/readonly-stack-09-release
Closed

refactor(release): readonly-domain-types (stack 9/12, re-split #307)#382
YosefHayim wants to merge 1 commit into
refactor/types/readonly-stack-08-configfrom
refactor/types/readonly-stack-09-release

Conversation

@YosefHayim

@YosefHayim YosefHayim commented Aug 7, 2026

Copy link
Copy Markdown
Owner

User description

Stack 9/12 of re-split HOLD #307

Domain: release
Base: refactor/types/readonly-stack-08-config
Full green tip: refactor/foundation/readonly-types-full

Land stack in order. Intermediate PRs may not typecheck alone.


Summary by cubic

Shifted the release domain to read-only types to prevent accidental mutations, with local MutableDeep usage where mutation is required. No runtime behavior changes.

  • Refactors
    • Accept readonly arrays in downloadFeedbackAttachments and highestVersion.
    • Use MutableDeep for locally mutable copies in tests and release-train orchestrator.
    • Replace cars.filter(isNativeCar) with an explicit loop to maintain narrowed MutableDeep types.
    • Remove Schema.mutable wrappers in record.ts and keep TrainRecord schemas plain, aligning with readonly domain types.

Written for commit dc43b57. Summary will update on new commits.

Review in cubic


CodeAnt-AI Description

Preserve release workflow behavior while supporting readonly release data

What Changed

  • Release train creation, advancement, version comparison, and feedback attachment handling continue to produce the same results with readonly inputs
  • Release train records are handled without changing their stored shape or state transitions
  • Existing release status and failure handling behavior remains unchanged

Impact

✅ Unchanged release train outcomes
✅ Unchanged version selection
✅ Unchanged feedback attachment downloads

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

@codeant-ai

codeant-ai Bot commented Aug 7, 2026

Copy link
Copy Markdown

🤖 CodeAnt AI — Review Status

Status Commit Started (UTC) Finished (UTC)
✅ Reviewed your PR dc43b57 Aug 07, 2026 · 11:07 11:09

@changeset-bot

changeset-bot Bot commented Aug 7, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: dc43b57

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@codeant-ai

codeant-ai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@codeant-ai codeant-ai Bot added the size:M This PR changes 30-99 lines, ignoring generated files label Aug 7, 2026
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

refactor(release): align release + release-train consumers with readonly domain types

✨ Enhancement 🧪 Tests 🕐 20-40 Minutes

Grey Divider

AI Description

• Accept readonly arrays in TestFlight feedback downloads and version selection helpers.
• Use MutableDeep for local mutable copies in tests and release-train orchestration.
• Remove Schema.mutable wrappers so persisted TrainRecord schemas match readonly domain types.
Diagram

graph TD
  A["Release helpers"] --> B(["Readonly inputs"])
  C["Release-train orchestrator"] --> D(["MutableDeep copies"])
  E["TrainRecord persistence"] --> F["Readonly Train types"]
  C --> F
  A --> F
  G["Status command tests"] --> D

  subgraph Legend
    direction LR
    _mod["Module/File"] ~~~ _ro(["Readonly types/inputs"]) ~~~ _mut(["Local mutable copy"])
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Prefer immutable update style (no `MutableDeep`)
  • ➕ Avoids introducing writable escape hatches, keeping readonly guarantees stronger
  • ➕ Often produces clearer diffs for state transitions (new object per step)
  • ➖ More verbose in state-machine code (needs object reconstruction at each transition)
  • ➖ Can be harder to keep type narrowing ergonomic without additional helpers
2. Introduce small builder/helpers for test and car construction
  • ➕ Keeps mutation localized behind helper APIs (e.g., makeNativeCar(...))
  • ➕ Reduces repeated MutableDeep annotations across call sites
  • ➖ Adds indirection and extra utilities to maintain
  • ➖ May still require casts/writable types internally

Recommendation: The PR’s approach is reasonable for a staged readonly-migration: keep domain types readonly at boundaries and use MutableDeep only for local, short-lived mutations (tests, orchestration). If MutableDeep usage starts spreading, consider consolidating it behind builders or moving the orchestrator to an immutable-update style to preserve stronger readonly guarantees.

Files changed (5) +47 / -47

Refactor (4) +45 / -46
testflightFeedback.tsAccept readonly feedback entries in attachment downloader +1/-1

Accept readonly feedback entries in attachment downloader

• Changes 'downloadFeedbackAttachments' to accept 'readonly BetaFeedback[]', aligning the API with readonly domain conventions while keeping iteration logic unchanged.

src/core/release/testflightFeedback.ts

version.tsMake 'highestVersion' accept readonly version lists +1/-1

Make 'highestVersion' accept readonly version lists

• Updates 'highestVersion' to take 'readonly string[]', allowing callers with immutable arrays to use it without casts and preventing accidental mutation of inputs.

src/core/release/version.ts

orchestrator.tsUse 'MutableDeep' local copies for train car mutation and preserve narrowing +8/-3

Use 'MutableDeep' local copies for train car mutation and preserve narrowing

• Creates locally mutable 'NativeCar'/'Car' copies via 'MutableDeep' to support in-place state transitions while keeping 'TrainRecord' types readonly. Replaces a 'filter(isNativeCar)' call with an explicit loop to maintain correct narrowing for 'MutableDeep<NativeCar>' arrays.

src/core/releaseTrain/orchestrator.ts

record.tsRemove 'Schema.mutable' wrappers from train record schemas +35/-41

Remove 'Schema.mutable' wrappers from train record schemas

• Replaces 'Schema.mutable(...)' usage with plain 'Schema.Struct'/'Schema.Array' definitions so runtime schemas align with readonly 'TrainRecord' and car types. Persistence behavior should remain unchanged; the change is focused on schema/type compatibility.

src/core/releaseTrain/record.ts

Tests (1) +2 / -1
statusCommand.test.tsUse 'MutableDeep' when constructing mutable 'AppDescriptor' test fixtures +2/-1

Use 'MutableDeep' when constructing mutable 'AppDescriptor' test fixtures

• Imports 'MutableDeep' and uses it for the locally-built 'appDescriptor' so optional fields can be assigned without fighting readonly typing. Test behavior remains the same; this is strictly a typing/fixture-construction adjustment.

src/core/release/statusCommand.test.ts

@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider

Great, no issues found!

Qodo reviewed your code and found no material issues that require review

Grey Divider

To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Qodo Logo

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 842c391c-03be-4f06-ba5a-15c5ae1c86e2

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

@cubic-dev-ai cubic-dev-ai 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.

No issues found across 5 files

Re-trigger cubic

@YosefHayim

Copy link
Copy Markdown
Owner Author

Superseded by land of tip stack #386 (same 12 domain commits).

@YosefHayim YosefHayim closed this Aug 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M This PR changes 30-99 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant