Skip to content

Conversation

@d-gubert
Copy link
Member

@d-gubert d-gubert commented Oct 8, 2025

Proposed changes (including videos or screenshots)

Issue(s)

Steps to test or reproduce

Further comments

ARCH-1792

Summary by CodeRabbit

  • Refactor

    • Simplified app initialization, enabling, installation, and startup flows with consolidated status handling.
  • Behavior

    • No longer persists every intermediate app status; status persistence centralized. New/installed apps now default to manually_enabled or manually_disabled on install/startup.
  • Tests

    • End-to-end tests updated to expect installed apps as "manually_enabled".
  • Chores

    • Added a changeset documenting the status persistence behavior change.

@dionisio-bot
Copy link
Contributor

dionisio-bot bot commented Oct 8, 2025

Looks like this PR is ready to merge! 🎉
If you have any trouble, please check the PR guidelines

@changeset-bot
Copy link

changeset-bot bot commented Oct 8, 2025

🦋 Changeset detected

Latest commit: 4c145ca

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 42 packages
Name Type
@rocket.chat/apps-engine Minor
@rocket.chat/meteor Minor
@rocket.chat/apps Patch
@rocket.chat/core-services Patch
@rocket.chat/core-typings Minor
@rocket.chat/fuselage-ui-kit Major
@rocket.chat/rest-typings Minor
@rocket.chat/ddp-streamer Patch
@rocket.chat/presence Patch
rocketchat-services Patch
@rocket.chat/uikit-playground Patch
@rocket.chat/api-client Patch
@rocket.chat/cron Patch
@rocket.chat/ddp-client Patch
@rocket.chat/freeswitch Patch
@rocket.chat/gazzodown Major
@rocket.chat/http-router Patch
@rocket.chat/livechat Patch
@rocket.chat/model-typings Patch
@rocket.chat/ui-avatar Major
@rocket.chat/ui-client Major
@rocket.chat/ui-contexts Major
@rocket.chat/web-ui-registration Major
@rocket.chat/account-service Patch
@rocket.chat/authorization-service Patch
@rocket.chat/omnichannel-transcript Patch
@rocket.chat/presence-service Patch
@rocket.chat/queue-worker Patch
@rocket.chat/stream-hub-service Patch
@rocket.chat/federation-matrix Patch
@rocket.chat/license Patch
@rocket.chat/media-calls Patch
@rocket.chat/omnichannel-services Patch
@rocket.chat/pdf-worker Patch
@rocket.chat/models Patch
@rocket.chat/network-broker Patch
@rocket.chat/omni-core-ee Patch
@rocket.chat/mock-providers Patch
@rocket.chat/ui-video-conf Major
@rocket.chat/ui-voip Major
@rocket.chat/instance-status Patch
@rocket.chat/omni-core Patch

Not sure what this means? Click here to learn what changesets are.

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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 8, 2025

Walkthrough

Refactors AppManager internals to use ProxiedApp-centric signatures, centralizes persistence so only desired app status is stored in the DB, updates a REST callsite to use changeStatus(..., AppStatus.MANUALLY_ENABLED), and updates tests/assertions to expect manually_enabled.

Changes

Cohort / File(s) Summary
App Manager refactor
packages/apps-engine/src/server/AppManager.ts
Updated private/public method signatures (initializeApp, runStartUpProcess, enableApp, installApp) to accept ProxiedApp and silenceStatus; removed per-call runtime status DB writes and centralized desired-status persistence.
Changelog / changeset
.changeset/real-pans-confess.md
Adds changeset documenting behavioral change: runtime/intermediate status transitions are no longer persisted; bumps package versions.
REST status handling
apps/meteor/ee/server/apps/communication/rest.ts
Replaced enable(info.id) with changeStatus(info.id, AppStatus.MANUALLY_ENABLED) and uses returned object's getStatus() for response.
End-to-end tests
apps/meteor/tests/end-to-end/api/livechat/00-rooms.ts, apps/meteor/tests/end-to-end/apps/installation.ts
Assertions updated to expect manually_enabled instead of auto_enabled.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant AppManager
    participant ProxiedApp
    participant DB

    rect rgba(220,180,200,0.12)
    Note right of AppManager: Old flow — per-call runtime status writes
    Client->>AppManager: initializeApp(storageItem, app, saveToDb?)
    AppManager->>ProxiedApp: initialize()
    AppManager->>DB: save(runtime status)
    end

    rect rgba(180,220,200,0.12)
    Note right of AppManager: New flow — ProxiedApp-centric, persist desired status only
    Client->>AppManager: initializeApp(ProxiedApp, silenceStatus?)
    AppManager->>ProxiedApp: initialize()
    AppManager->>DB: save(desired status)
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Pay extra attention to:
    • packages/apps-engine/src/server/AppManager.ts for signature changes and centralized persistence points.
    • apps/meteor/ee/server/apps/communication/rest.ts for API and return-type handling.
    • Tests updated to reflect new status semantics.

Possibly related PRs

Suggested reviewers

  • ggazzo

Poem

🐰 I hopped through code with nimble paws,
I nudged the statuses into one small cause,
Desired states tucked where they belong,
Runtime whispers hum a softer song,
A neat, warm burrow — quiet and strong.

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: stopping persistence of intermediate app status transitions to the database, which aligns with the PR's core objective.
Linked Issues check ✅ Passed The PR successfully implements the core requirements from ARCH-1792: AppManager now persists only desired target status rather than intermediate transitions, with status set to MANUALLY_ENABLED or MANUALLY_DISABLED based on user intent.
Out of Scope Changes check ✅ Passed All changes are scoped to implementing ARCH-1792 requirements: AppManager signature refactoring, centralized status persistence, and updated test assertions. No unrelated modifications detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/apps-target-status

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 and usage tips.

@codecov
Copy link

codecov bot commented Oct 8, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 68.11%. Comparing base (7b176ff) to head (4c145ca).
⚠️ Report is 3 commits behind head on develop.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop   #37167      +/-   ##
===========================================
- Coverage    68.13%   68.11%   -0.02%     
===========================================
  Files         3364     3364              
  Lines       115753   115753              
  Branches     20914    20909       -5     
===========================================
- Hits         78866    78846      -20     
- Misses       34192    34213      +21     
+ Partials      2695     2694       -1     
Flag Coverage Δ
e2e 57.47% <ø> (-0.01%) ⬇️
unit 72.13% <ø> (-0.03%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@d-gubert d-gubert force-pushed the feat/apps-target-status branch 3 times, most recently from 47356e7 to aa6bc50 Compare October 9, 2025 20:18
@d-gubert d-gubert force-pushed the feat/apps-target-status branch from 6e4372d to bd0f5a9 Compare October 27, 2025 17:41
@d-gubert
Copy link
Member Author

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 27, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

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 (1)
packages/apps-engine/src/server/AppManager.ts (1)

856-877: Remove redundant in-memory status updates in changeStatus() method.

The code updates storageItem.status at lines 866 and 875, but these are unnecessary since updateStatus() directly persists to the database without reading from the local storageItem object. After these lines execute, the method returns rl rather than storageItem, so the in-memory updates have no functional purpose.

Suggested fix: Remove lines 866 and 875 to simplify the code:

// Enable branch (lines 858-867)
if (AppStatusUtils.isEnabled(status)) {
	if (AppStatusUtils.isEnabled(await rl.getStatus())) {
		throw new Error('Can not enable an App which is already enabled.');
	}

	await this.enable(rl.getID());

	await this.appMetadataStorage.updateStatus(storageItem._id, AppStatus.MANUALLY_ENABLED);
} else {
	// Disable branch (lines 868-876)
	if (!AppStatusUtils.isEnabled(await rl.getStatus())) {
		throw new Error('Can not disable an App which is not enabled.');
	}

	await this.disable(rl.getID(), AppStatus.MANUALLY_DISABLED);

	await this.appMetadataStorage.updateStatus(storageItem._id, AppStatus.MANUALLY_DISABLED);
}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 5c7e8ec and bd0f5a9.

📒 Files selected for processing (1)
  • packages/apps-engine/src/server/AppManager.ts (12 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: 🚢 Build Docker Images for Testing (alpine)
🔇 Additional comments (7)
packages/apps-engine/src/server/AppManager.ts (7)

313-313: LGTM: Simplified initializeApp signature.

The refactored call correctly passes the app instance and silences status updates during bulk initialization.


332-332: LGTM: Refactored enableApp call.

The isManual flag correctly reflects whether the app was previously manually enabled, aligning with the objective to track desired status.


636-644: LGTM: Simplified method calls.

The refactored installApp and initializeApp calls correctly use the new signatures, removing the now-unnecessary storageItem parameters.


824-824: LGTM: Updated to new signature.

The initializeApp call correctly uses the refactored signature.


967-974: LGTM: Refactored method calls.

Both initializeApp and enableApp calls correctly use the new signatures and properly determine the isManual flag from the previous status.


987-998: LGTM: Startup process refactored correctly.

The runStartUpProcess method correctly uses the new method signatures for initializeApp and enableApp, passing the appropriate parameters including the isManual flag.


1001-1116: LGTM: Refactored signatures align with PR objectives.

The simplified method signatures effectively support the separation of target status from runtime status:

  • installApp (line 1001): Removed storageItem parameter, now takes only app and user.
  • initializeApp (line 1038): Streamlined to (app, silenceStatus), removing storageItem and saveToDb parameters.
  • enableApp (line 1116): Refactored to (app, isManual, silenceStatus), removing storageItem and saveToDb. The isManual flag explicitly tracks whether the enable action represents user intent (desired status) versus automatic state, which directly supports the PR's goal of storing only desired status in the database.

These changes improve clarity and ensure that manual vs. automatic status distinctions are explicit throughout the app lifecycle.

@d-gubert d-gubert added this to the 7.13.0 milestone Oct 27, 2025
@d-gubert d-gubert force-pushed the feat/apps-target-status branch from 2e90cbf to bcffc9c Compare October 28, 2025 18:04
@d-gubert d-gubert changed the title feat(apps): separate target status and running status feat(apps): stop persisting status transitions to database Oct 28, 2025
@d-gubert d-gubert marked this pull request as ready for review October 29, 2025 12:50
@d-gubert d-gubert requested review from a team as code owners October 29, 2025 12:50
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
packages/apps-engine/src/server/AppManager.ts (1)

856-856: Remove unnecessary await keyword.

The getStorageItem() method returns IAppStorageItem synchronously (not a Promise), so the await keyword here is unnecessary and misleading.

Apply this diff:

-		const storageItem = await rl.getStorageItem();
+		const storageItem = rl.getStorageItem();
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between bd0f5a9 and 6d44bc7.

📒 Files selected for processing (5)
  • .changeset/real-pans-confess.md (1 hunks)
  • apps/meteor/ee/server/apps/communication/rest.ts (1 hunks)
  • apps/meteor/tests/end-to-end/api/livechat/00-rooms.ts (1 hunks)
  • apps/meteor/tests/end-to-end/apps/installation.ts (1 hunks)
  • packages/apps-engine/src/server/AppManager.ts (12 hunks)
✅ Files skipped from review due to trivial changes (1)
  • .changeset/real-pans-confess.md
🧰 Additional context used
🧬 Code graph analysis (1)
packages/apps-engine/src/server/AppManager.ts (1)
packages/apps-engine/src/server/ProxiedApp.ts (1)
  • ProxiedApp (16-160)
🔇 Additional comments (10)
packages/apps-engine/src/server/AppManager.ts (7)

313-313: LGTM!

The initializeApp call correctly uses the new signature accepting the ProxiedApp directly with silenceStatus=true.


332-332: LGTM!

The enableApp call correctly determines isManual from the previous status, preserving the manual/auto distinction across server restarts.


561-561: LGTM! Past review concern addressed.

The descriptor status now correctly reflects the enable parameter, setting MANUALLY_ENABLED when enabled and MANUALLY_DISABLED when disabled. This resolves the status inconsistency flagged in the previous review.


636-636: LGTM!

The installApp call uses the new simplified signature accepting ProxiedApp directly.


866-867: LGTM!

The status persistence pattern correctly updates both the in-memory storageItem and the database, ensuring consistency. This aligns with the PR's objective to persist only the desired status.

Also applies to: 875-876


967-967: LGTM!

All method calls use the new signatures consistently, passing ProxiedApp directly and propagating silenceStatus and isManual parameters appropriately.

Also applies to: 974-974, 987-987, 998-998


1001-1001: LGTM!

The private method signatures have been successfully refactored to accept ProxiedApp directly, simplifying the API and improving consistency. All call sites have been updated to match these new signatures.

Also applies to: 1038-1038, 1116-1116

apps/meteor/tests/end-to-end/api/livechat/00-rooms.ts (1)

104-104: LGTM!

The test expectation correctly updated to reflect the new behavior where installed apps have a status of manually_enabled instead of auto_enabled.

apps/meteor/tests/end-to-end/apps/installation.ts (1)

55-55: LGTM!

The test expectation correctly updated to manually_enabled, consistent with the new app status management approach.

apps/meteor/ee/server/apps/communication/rest.ts (1)

477-478: LGTM!

The REST API correctly updated to use the new changeStatus method and retrieves the status from the returned ProxiedApp object, aligning with the refactored status management flow.

@d-gubert d-gubert force-pushed the feat/apps-target-status branch from 6d44bc7 to 9d5a6af Compare October 29, 2025 14:08
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

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 (1)
packages/apps-engine/src/server/AppManager.ts (1)

1001-1018: Well-executed refactoring of private helper methods.

The method signatures have been simplified to accept ProxiedApp directly:

  • installApp(app: ProxiedApp, user: IUser) (line 1001)
  • initializeApp(app: ProxiedApp, silenceStatus = false) (line 1038)
  • enableApp(app: ProxiedApp, isManual: boolean, silenceStatus = false) (line 1116)

These methods correctly manage runtime status transitions without persisting them to the database, using app.setStatus() for runtime state changes. All call sites have been updated consistently throughout the file.

Also applies to: 1038-1069, 1116-1164

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 6d44bc7 and 9d5a6af.

📒 Files selected for processing (5)
  • .changeset/real-pans-confess.md (1 hunks)
  • apps/meteor/ee/server/apps/communication/rest.ts (1 hunks)
  • apps/meteor/tests/end-to-end/api/livechat/00-rooms.ts (1 hunks)
  • apps/meteor/tests/end-to-end/apps/installation.ts (1 hunks)
  • packages/apps-engine/src/server/AppManager.ts (12 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • apps/meteor/tests/end-to-end/api/livechat/00-rooms.ts
  • apps/meteor/ee/server/apps/communication/rest.ts
  • .changeset/real-pans-confess.md
  • apps/meteor/tests/end-to-end/apps/installation.ts
🧰 Additional context used
🧬 Code graph analysis (1)
packages/apps-engine/src/server/AppManager.ts (1)
packages/apps-engine/src/server/ProxiedApp.ts (1)
  • ProxiedApp (16-160)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: 🔎 Code Check / TypeScript
  • GitHub Check: CodeQL-Build
  • GitHub Check: CodeQL-Build
🔇 Additional comments (2)
packages/apps-engine/src/server/AppManager.ts (2)

561-561: LGTM! Past review concern addressed.

The status is now correctly set based on the enable parameter. The database will store MANUALLY_ENABLED when enable=true and MANUALLY_DISABLED when enable=false, properly reflecting the desired status as per the PR objectives.


856-880: Correct implementation of desired status persistence.

The changeStatus method appropriately persists only the desired status (MANUALLY_ENABLED or MANUALLY_DISABLED) to the database at lines 867 and 876. This aligns with the PR objectives:

  • Desired status changes are explicitly persisted to the database
  • Runtime status changes in initializeApp and enableApp are NOT persisted
  • This prevents transient runtime states from affecting other instances

@d-gubert d-gubert force-pushed the feat/apps-target-status branch from 9d5a6af to 25ba513 Compare October 30, 2025 18:47
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
packages/apps-engine/src/server/AppManager.ts (1)

332-332: Consider passing silenceStatus consistently.

At line 313, initializeApp is called with silenceStatus=true, but line 332 calls enableApp without passing the silenceStatus parameter (defaulting to false). If the intent is to silence status notifications during the entire enableAll startup process, consider passing true explicitly here as well for consistency.

-				await this.enableApp(app).catch(console.error);
+				await this.enableApp(app, true).catch(console.error);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 9d5a6af and 25ba513.

📒 Files selected for processing (5)
  • .changeset/real-pans-confess.md (1 hunks)
  • apps/meteor/ee/server/apps/communication/rest.ts (1 hunks)
  • apps/meteor/tests/end-to-end/api/livechat/00-rooms.ts (1 hunks)
  • apps/meteor/tests/end-to-end/apps/installation.ts (1 hunks)
  • packages/apps-engine/src/server/AppManager.ts (13 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/meteor/tests/end-to-end/api/livechat/00-rooms.ts
  • .changeset/real-pans-confess.md
🧰 Additional context used
🧠 Learnings (12)
📚 Learning: 2025-10-06T20:32:23.658Z
Learnt from: d-gubert
PR: RocketChat/Rocket.Chat#37152
File: packages/apps-engine/tests/test-data/utilities.ts:557-573
Timestamp: 2025-10-06T20:32:23.658Z
Learning: In packages/apps-engine/tests/test-data/utilities.ts, the field name `isSubscripbedViaBundle` in the `IMarketplaceSubscriptionInfo` type should not be flagged as a typo, as it may match the upstream API's field name.

Applied to files:

  • packages/apps-engine/src/server/AppManager.ts
📚 Learning: 2025-09-30T13:00:05.465Z
Learnt from: d-gubert
PR: RocketChat/Rocket.Chat#36990
File: apps/meteor/ee/server/apps/storage/AppRealStorage.ts:55-58
Timestamp: 2025-09-30T13:00:05.465Z
Learning: In AppRealStorage (apps/meteor/ee/server/apps/storage/AppRealStorage.ts), the `remove` method is designed to be idempotent and returns `{ success: true }` unconditionally because the goal is to ensure the app is removed, not to distinguish whether this specific call performed the deletion. Database errors will throw exceptions.

Applied to files:

  • packages/apps-engine/src/server/AppManager.ts
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
PR: RocketChat/Rocket.Chat#0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use descriptive test names that clearly communicate expected behavior

Applied to files:

  • apps/meteor/tests/end-to-end/apps/installation.ts
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
PR: RocketChat/Rocket.Chat#0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Prefer web-first assertions (e.g., toBeVisible, toHaveText)

Applied to files:

  • apps/meteor/tests/end-to-end/apps/installation.ts
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
PR: RocketChat/Rocket.Chat#0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.{ts,tsx,js,jsx} : Avoid code comments in the implementation

Applied to files:

  • apps/meteor/tests/end-to-end/apps/installation.ts
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
PR: RocketChat/Rocket.Chat#0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Ensure tests run reliably in parallel without shared state conflicts

Applied to files:

  • apps/meteor/tests/end-to-end/apps/installation.ts
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
PR: RocketChat/Rocket.Chat#0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Ensure a clean state for each test execution

Applied to files:

  • apps/meteor/tests/end-to-end/apps/installation.ts
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
PR: RocketChat/Rocket.Chat#0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : All Playwright test files must be located under apps/meteor/tests/e2e/ and use the .spec.ts extension (e.g., login.spec.ts)

Applied to files:

  • apps/meteor/tests/end-to-end/apps/installation.ts
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
PR: RocketChat/Rocket.Chat#0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Maintain test isolation between test cases

Applied to files:

  • apps/meteor/tests/end-to-end/apps/installation.ts
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
PR: RocketChat/Rocket.Chat#0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use expect matchers (toEqual, toContain, toBeTruthy, toHaveLength, etc.) instead of assert statements

Applied to files:

  • apps/meteor/tests/end-to-end/apps/installation.ts
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
PR: RocketChat/Rocket.Chat#0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.{ts,tsx,js,jsx} : Write concise, technical TypeScript/JavaScript with accurate typing

Applied to files:

  • apps/meteor/tests/end-to-end/apps/installation.ts
📚 Learning: 2025-09-16T22:08:51.490Z
Learnt from: CR
PR: RocketChat/Rocket.Chat#0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-09-16T22:08:51.490Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Utilize Playwright fixtures (test, page, expect) consistently

Applied to files:

  • apps/meteor/tests/end-to-end/apps/installation.ts
🧬 Code graph analysis (1)
packages/apps-engine/src/server/AppManager.ts (1)
packages/apps-engine/src/server/ProxiedApp.ts (1)
  • ProxiedApp (16-160)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: 📦 Build Packages
  • GitHub Check: CodeQL-Build
  • GitHub Check: CodeQL-Build
🔇 Additional comments (6)
apps/meteor/ee/server/apps/communication/rest.ts (1)

477-478: LGTM! Status handling is now explicit and clear.

The change from enable() to changeStatus(info.id, AppStatus.MANUALLY_ENABLED) aligns well with the PR's objective to persist only the desired status. The explicit status parameter makes the intent clear, and retrieving the status via getStatus() ensures consistency with the app's actual state.

packages/apps-engine/src/server/AppManager.ts (4)

561-561: Good fix! Status now correctly reflects the enable parameter.

The conditional status assignment addresses the previous review concern. The database now correctly stores MANUALLY_DISABLED when enable=false, ensuring the persisted state matches the user's intent.


1111-1159: LGTM! Runtime status handling without DB persistence.

The enableApp method correctly sets the runtime status to MANUALLY_ENABLED (line 1122) without directly persisting to the database. This aligns with the PR's objective: transient runtime status changes are not persisted, and only explicit user actions via changeStatus() write to the DB.


642-644: Add integration tests covering app installation status flow with server restart.

The code alignment at lines 561, 642, and 1122 is correct. However, verification found no integration tests covering the installation flow when enable=true, specifically:

  • Status persistence from initial MANUALLY_ENABLED (line 561) through app startup (line 642)
  • Runtime status set to MANUALLY_ENABLED (line 1122) via enableApp
  • Status retention after server restart

Before merging, ensure integration tests are added to verify this complete flow, as current test coverage for this scenario is absent.


856-877: The in-memory update serves cache consistency but consider order of operations.

The storageItem.status update (lines 866, 875) maintains consistency with the cached storage object returned by getStorageItem(). However, since updateStatus() is called with explicit status values rather than storageItem.status, and the in-memory update precedes the awaited database write, consider whether updating the cache after the database write succeeds would be safer—preventing stale cache if updateStatus() fails.

apps/meteor/tests/end-to-end/apps/installation.ts (1)

55-55: LGTM! Test assertion updated to match new status handling.

The expected status change from 'auto_enabled' to 'manually_enabled' correctly reflects the implementation changes in AppManager where successful installations now explicitly set AppStatus.MANUALLY_ENABLED. This ensures test coverage aligns with the PR's objective to persist only the desired (manually set) status.

@d-gubert d-gubert changed the title feat(apps): stop persisting status transitions to database feat(apps): stop persisting intermediate status transitions to database Nov 3, 2025
@d-gubert d-gubert force-pushed the feat/apps-target-status branch from 25ba513 to 220b797 Compare November 7, 2025 17:16
@d-gubert d-gubert added the stat: QA assured Means it has been tested and approved by a company insider label Nov 10, 2025
@dionisio-bot dionisio-bot bot added the stat: ready to merge PR tested and approved waiting for merge label Nov 10, 2025
@d-gubert d-gubert force-pushed the feat/apps-target-status branch from 220b797 to 4c145ca Compare November 10, 2025 17:21
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

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 (1)
packages/apps-engine/src/server/AppManager.ts (1)

437-463: Consider making enable() private.

The enable() method doesn't persist status changes to the database—only changeStatus() does (lines 866-867). Since the REST API and other external callers have been updated to use changeStatus() instead, enable() now serves as an internal helper. Making it private would clarify its role and prevent external callers from bypassing persistence.

Apply this diff to make the method private:

-	public async enable(id: string): Promise<boolean> {
+	private async enable(id: string): Promise<boolean> {
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 220b797 and 4c145ca.

📒 Files selected for processing (5)
  • .changeset/real-pans-confess.md (1 hunks)
  • apps/meteor/ee/server/apps/communication/rest.ts (1 hunks)
  • apps/meteor/tests/end-to-end/api/livechat/00-rooms.ts (1 hunks)
  • apps/meteor/tests/end-to-end/apps/installation.ts (1 hunks)
  • packages/apps-engine/src/server/AppManager.ts (13 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • .changeset/real-pans-confess.md
  • apps/meteor/tests/end-to-end/api/livechat/00-rooms.ts
  • apps/meteor/ee/server/apps/communication/rest.ts
  • apps/meteor/tests/end-to-end/apps/installation.ts
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-10-06T20:32:23.658Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 37152
File: packages/apps-engine/tests/test-data/utilities.ts:557-573
Timestamp: 2025-10-06T20:32:23.658Z
Learning: In packages/apps-engine/tests/test-data/utilities.ts, the field name `isSubscripbedViaBundle` in the `IMarketplaceSubscriptionInfo` type should not be flagged as a typo, as it may match the upstream API's field name.

Applied to files:

  • packages/apps-engine/src/server/AppManager.ts
📚 Learning: 2025-09-30T13:00:05.465Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 36990
File: apps/meteor/ee/server/apps/storage/AppRealStorage.ts:55-58
Timestamp: 2025-09-30T13:00:05.465Z
Learning: In AppRealStorage (apps/meteor/ee/server/apps/storage/AppRealStorage.ts), the `remove` method is designed to be idempotent and returns `{ success: true }` unconditionally because the goal is to ensure the app is removed, not to distinguish whether this specific call performed the deletion. Database errors will throw exceptions.

Applied to files:

  • packages/apps-engine/src/server/AppManager.ts
🧬 Code graph analysis (1)
packages/apps-engine/src/server/AppManager.ts (2)
packages/apps-engine/src/server/ProxiedApp.ts (1)
  • ProxiedApp (16-160)
packages/core-typings/src/IUser.ts (1)
  • IUser (186-255)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: CodeQL-Build
🔇 Additional comments (6)
packages/apps-engine/src/server/AppManager.ts (6)

313-313: LGTM! Initialization silenced appropriately during startup.

During enableAll, initialization notifications are silenced (line 313), while enabling notifications remain active (line 332). This ensures the UI is notified when apps reach their final enabled state without intermediate initialization noise.


558-568: ✅ Past issue resolved: Descriptor status now correctly reflects enable parameter.

The descriptor status is now appropriately set to MANUALLY_ENABLED when enable=true and MANUALLY_DISABLED when enable=false (line 561). This ensures the database stores the correct desired status from the start.


640-645: ✅ Past issue resolved: Runtime status now matches database status.

The previous inconsistency where runStartUpProcess was called with isManual=false (causing AUTO_ENABLED runtime status while DB had MANUALLY_ENABLED) has been resolved. The parameter was renamed to silenceStatus (which controls notifications, not status value), and enableApp now always sets MANUALLY_ENABLED on success (line 1122). This ensures runtime and database status remain consistent from installation onward.


856-877: LGTM! Desired status persistence correctly centralized.

The changeStatus method properly centralizes desired status persistence per the PR objectives. After calling enable() or disable() to set runtime status, it explicitly updates the in-memory storageItem.status and persists to the database (lines 866-867, 875-876). This ensures:

  1. Runtime status changes don't auto-persist (avoiding intermediate transitions in DB)
  2. Desired status is explicitly persisted only when changed by user intent
  3. In-memory storage item stays consistent with persisted state

980-994: LGTM! Clean refactoring to app-centric signatures.

The runStartUpProcess method has been refactored to delegate initialization and enabling to dedicated methods (initializeApp and enableApp) while maintaining the storageItem parameter only for required settings validation. The silenceStatus parameter is properly threaded through to control notification behavior. This aligns well with the PR's goal of centralizing status management.


1111-1159: LGTM! Always using MANUALLY_ENABLED resolves previous inconsistency.

The enableApp method now consistently sets status = AppStatus.MANUALLY_ENABLED on success (line 1122), removing the previous distinction between manual and automatic enabling that caused runtime/DB mismatches. The status is set via app.setStatus() (line 1156), which updates runtime status without persisting to the database—persistence is handled separately by changeStatus(). This correctly implements the PR objective of avoiding intermediate status persistence.

@kodiakhq kodiakhq bot merged commit a05b8f7 into develop Nov 10, 2025
64 checks passed
@kodiakhq kodiakhq bot deleted the feat/apps-target-status branch November 10, 2025 18:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

stat: QA assured Means it has been tested and approved by a company insider stat: ready to merge PR tested and approved waiting for merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants