Skip to content

Conversation

@prateekshourya29
Copy link
Member

@prateekshourya29 prateekshourya29 commented Dec 3, 2025

Description

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • Feature (non-breaking change which adds functionality)
  • Improvement (change that would cause existing functionality to not work as expected)
  • Code refactoring
  • Performance improvements
  • Documentation update

Screenshots and Media (if applicable)

Test Scenarios

References

Summary by CodeRabbit

  • New Features

    • Added product updates changelog display with iframe support and fallback UI
    • Implemented self-managed instance detection in configuration
  • Refactor

    • Simplified product updates modal architecture
    • Updated image picker tab options to be configuration-aware
    • Enhanced empty state component with alignment customization
  • UI Updates

    • Removed logo from product updates header
    • Marketing consent visibility now based on deployment type

✏️ Tip: You can customize this high-level summary in your review settings.

@makeplane
Copy link

makeplane bot commented Dec 3, 2025

Linked to Plane Work Item(s)

This comment was auto-generated by Plane

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 3, 2025

Walkthrough

This change introduces a new self-managed deployment flag throughout the system. It adds a changelog display component with fallback UI, expands the asset library with changelog illustrations, and conditionally renders UI elements based on deployment type (self-managed vs. cloud).

Changes

Cohort / File(s) Summary
Backend Configuration
apps/api/plane/settings/common.py, apps/api/plane/license/api/views/instance.py, packages/types/src/instance/base.ts
Added IS_SELF_MANAGED config flag and is_self_managed property to IInstanceConfig. Updated instance API endpoint to expose this flag in response. Reformatted REST_FRAMEWORK authentication classes.
Product Updates Components
apps/web/ce/components/global/product-updates/changelog.tsx, apps/web/ce/components/global/product-updates/header.tsx, apps/web/core/components/global/product-updates/modal.tsx, apps/web/core/components/global/product-updates/fallback.tsx
Created new ProductUpdatesChangelog component rendering iframe-based changelog with 15-second timeout and error handling. Added ProductUpdatesFallback component with variant-dependent UI. Updated modal to use dedicated changelog component instead of inline iframe. Removed PlaneLogo from header.
Propel Asset Library
packages/propel/src/empty-state/assets/vertical-stack/changelog.tsx, packages/propel/src/empty-state/assets/* (asset-registry.tsx, asset-types.ts, vertical-stack/constant.tsx, vertical-stack/index.ts), packages/propel/src/empty-state/detailed-empty-state.tsx
Added ChangelogVerticalStackIllustration SVG component and registered it in asset registry. Extended VerticalStackAssetType union with "changelog". Added align prop to EmptyStateDetailed for center-alignment support.
Conditional UI Updates
apps/web/core/components/onboarding/steps/profile/root.tsx, apps/web/core/components/core/image-picker-popover.tsx, apps/web/ce/components/global/index.ts
Hid MarketingConsent form field when is_self_managed is true. Made image picker tab options memoized and configuration-aware. Removed product-updates-header re-export from barrel file.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Areas requiring extra attention:

  • Iframe timeout logic: The 15-second timeout implementation in ProductUpdatesChangelog for error state triggering
  • Conditional rendering patterns: Verify is_self_managed checks are consistently applied across MarketingConsent, fallback UI, and config variant handling
  • Asset registration completeness: Confirm all changelog asset entries are properly wired through registry, constant map, and type definitions
  • Module exports: Verify the removed product-updates-header export from apps/web/ce/components/global/index.ts doesn't break existing imports elsewhere

Poem

🐰 A banner flies with self-managed pride,
New changelog ills on the fallback side,
Assets bloom in the registry's keep,
While consent sleeps when self-managed runs deep,
Configuration flows—the dream takes flight! 🌟

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is completely empty—all template sections lack any content, explanatory text, test information, screenshots, or issue references. Fill in all required template sections: provide a detailed description of changes, select the Type of Change, add test scenarios, and link related issues (e.g., WEB-5290).
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: selfhosted check' directly relates to the main changeset, which adds self-managed instance detection across the application (IS_SELF_MANAGED flag, conditional rendering, fallback UI).
✨ 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-selfhosted-check

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.

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 (6)
apps/web/core/components/onboarding/steps/profile/root.tsx (1)

25-25: Guard against instanceConfig being undefined before config loads

If useInstance() ever returns a falsy/undefined config during initial load, instanceConfig.is_self_managed will throw at render. You can harden this by using optional chaining so the UI still falls back to “hosted” behavior until config is available:

-  const { config: instanceConfig } = useInstance();
+  const { config: instanceConfig } = useInstance();-      {/* Marketing Consent */}
-      {!instanceConfig.is_self_managed && (
+      {/* Marketing Consent */}
+      {!instanceConfig?.is_self_managed && (
         <MarketingConsent
           isChecked={!!watch("has_marketing_email_consent")}
           handleChange={(has_marketing_email_consent) =>
             setValue("has_marketing_email_consent", has_marketing_email_consent)
           }
         />
       )}

This avoids a potential runtime error without changing intended behavior for self‑managed vs cloud.

Also applies to: 59-62, 258-265

apps/web/core/components/core/image-picker-popover.tsx (1)

1-1: Wire hasUnsplashConfigured and isEnabled into tab rendering and fetching

Right now hasUnsplashConfigured and tab.isEnabled are computed but not actually used to change behavior: the Unsplash SWR call still runs unconditionally, and the Unsplash tab/panel visibility is driven only by unsplashImages/unsplashError. You can both avoid unnecessary Unsplash calls when not configured and make the intent explicit by:

  • Skipping the Unsplash fetch when not configured.
  • Hiding the Unsplash tab/panel when hasUnsplashConfigured is false.
  • Using tab.isEnabled in the tab list.

For example:

-  const { config } = useInstance();
-  // derived values
-  const hasUnsplashConfigured = config?.has_unsplash_configured || false;
+  const { config } = useInstance();
+  // derived values
+  const hasUnsplashConfigured = config?.has_unsplash_configured || false;-  const { data: unsplashImages, error: unsplashError } = useSWR(
-    `UNSPLASH_IMAGES_${searchParams}`,
-    () => fileService.getUnsplashImages(searchParams),
-    {
-      revalidateOnFocus: false,
-      revalidateOnReconnect: false,
-    }
-  );
+  const { data: unsplashImages, error: unsplashError } = useSWR(
+    hasUnsplashConfigured ? `UNSPLASH_IMAGES_${searchParams}` : null,
+    () => fileService.getUnsplashImages(searchParams),
+    {
+      revalidateOnFocus: false,
+      revalidateOnReconnect: false,
+    }
+  );-                {tabOptions.map((tab) => {
-                  if (!unsplashImages && unsplashError && tab.key === "unsplash") return null;
+                {tabOptions.map((tab) => {
+                  if (!tab.isEnabled) return null;
+                  if (!unsplashImages && unsplashError && tab.key === "unsplash") return null;
                   if (projectCoverImages && projectCoverImages.length === 0 && tab.key === "images") return null;
…
-              <Tab.Panels className="vertical-scrollbar scrollbar-md h-full w-full flex-1 overflow-y-auto overflow-x-hidden">
-                {(unsplashImages || !unsplashError) && (
+              <Tab.Panels className="vertical-scrollbar scrollbar-md h-full w-full flex-1 overflow-y-auto overflow-x-hidden">
+                {hasUnsplashConfigured && (unsplashImages || !unsplashError) && (
                   <Tab.Panel className="mt-4 h-full w-full space-y-4">

This makes the Unsplash integration explicitly config‑driven and prevents unnecessary external requests when Unsplash isn’t set up.

Also applies to: 19-28, 58-81, 83-96, 200-218, 221-286

apps/api/plane/settings/common.py (1)

75-75: Consider maintaining consistent tuple formatting.

The authentication classes tuple was reformatted to a single line, but other similar configuration tuples in the file (e.g., lines 76-80, 199-204) use multi-line formatting. While functionally equivalent, consistency improves readability.

apps/web/ce/components/global/product-updates/changelog.tsx (3)

10-10: Simplify loading state management.

The combination of isLoadingRef and isLoading state creates unnecessary complexity. The ref is used to prevent the timeout from triggering after the iframe loads, but this can be achieved more cleanly by clearing the timeout in the load handler.

Apply this refactor to simplify the state management:

 export const ProductUpdatesChangelog = observer(function ProductUpdatesChangelog() {
-  // refs
-  const isLoadingRef = useRef(true);
+  const timeoutRef = useRef<NodeJS.Timeout | null>(null);
   // states
   const [isLoading, setIsLoading] = useState(true);
   const [hasError, setHasError] = useState(false);
   // store hooks
   const { config } = useInstance();
   // derived values
   const changeLogUrl = config?.instance_changelog_url;
   const shouldShowFallback = !changeLogUrl || changeLogUrl === "" || hasError;

   // timeout fallback - if iframe doesn't load within 15 seconds, show error
   useEffect(() => {
     if (!changeLogUrl || changeLogUrl === "") {
       setIsLoading(false);
-      isLoadingRef.current = false;
       return;
     }

     setIsLoading(true);
     setHasError(false);
-    isLoadingRef.current = true;

-    const timeoutId = setTimeout(() => {
-      if (isLoadingRef.current) {
-        setHasError(true);
-        setIsLoading(false);
-        isLoadingRef.current = false;
-      }
+    timeoutRef.current = setTimeout(() => {
+      setHasError(true);
+      setIsLoading(false);
     }, 15000);

     return () => {
-      clearTimeout(timeoutId);
+      if (timeoutRef.current) {
+        clearTimeout(timeoutRef.current);
+      }
     };
   }, [changeLogUrl]);

   const handleIframeLoad = () => {
+    if (timeoutRef.current) {
+      clearTimeout(timeoutRef.current);
+      timeoutRef.current = null;
+    }
     setTimeout(() => {
-      isLoadingRef.current = false;
       setIsLoading(false);
     }, 1000);
   };

   const handleIframeError = () => {
-    isLoadingRef.current = false;
+    if (timeoutRef.current) {
+      clearTimeout(timeoutRef.current);
+      timeoutRef.current = null;
+    }
     setHasError(true);
     setIsLoading(false);
   };

Also applies to: 23-26, 28-30, 33-36, 47-48, 53-54


45-50: Remove arbitrary delay in iframe load handler.

The 1-second setTimeout in handleIframeLoad adds unnecessary delay to showing the loaded content. The iframe's onLoad event already fires when the content is ready, so this delay provides no benefit and degrades user experience.

 const handleIframeLoad = () => {
-  setTimeout(() => {
-    isLoadingRef.current = false;
-    setIsLoading(false);
-  }, 1000);
+  if (timeoutRef.current) {
+    clearTimeout(timeoutRef.current);
+    timeoutRef.current = null;
+  }
+  setIsLoading(false);
 };

32-38: Consider reducing timeout duration for better UX.

The 15-second timeout before showing the fallback UI is quite long. Users may perceive the application as frozen. Consider reducing this to 8-10 seconds, which still allows for slower network conditions but provides faster feedback.

-    }, 15000); // 15 second timeout
+    }, 10000); // 10 second timeout
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5f7ffcb and f287b48.

📒 Files selected for processing (16)
  • apps/api/plane/license/api/views/instance.py (1 hunks)
  • apps/api/plane/settings/common.py (2 hunks)
  • apps/web/ce/components/global/index.ts (0 hunks)
  • apps/web/ce/components/global/product-updates/changelog.tsx (1 hunks)
  • apps/web/ce/components/global/product-updates/header.tsx (1 hunks)
  • apps/web/core/components/core/image-picker-popover.tsx (3 hunks)
  • apps/web/core/components/global/product-updates/fallback.tsx (1 hunks)
  • apps/web/core/components/global/product-updates/modal.tsx (2 hunks)
  • apps/web/core/components/onboarding/steps/profile/root.tsx (3 hunks)
  • packages/propel/src/empty-state/assets/asset-registry.tsx (2 hunks)
  • packages/propel/src/empty-state/assets/asset-types.ts (1 hunks)
  • packages/propel/src/empty-state/assets/vertical-stack/changelog.tsx (1 hunks)
  • packages/propel/src/empty-state/assets/vertical-stack/constant.tsx (2 hunks)
  • packages/propel/src/empty-state/assets/vertical-stack/index.ts (1 hunks)
  • packages/propel/src/empty-state/detailed-empty-state.tsx (1 hunks)
  • packages/types/src/instance/base.ts (1 hunks)
💤 Files with no reviewable changes (1)
  • apps/web/ce/components/global/index.ts
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,mts,cts}

📄 CodeRabbit inference engine (.github/instructions/typescript.instructions.md)

**/*.{ts,tsx,mts,cts}: Use const type parameters for more precise literal inference in TypeScript 5.0+
Use the satisfies operator to validate types without widening them
Leverage inferred type predicates to reduce the need for explicit is return types in filter/check functions
Use NoInfer<T> utility to block inference for specific type arguments when they should be determined by other arguments
Utilize narrowing in switch(true) blocks for control flow analysis (TypeScript 5.3+)
Rely on narrowing from direct boolean comparisons for type guards
Trust preserved narrowing in closures when variables aren't modified after the check (TypeScript 5.4+)
Use constant indices to narrow object/array properties (TypeScript 5.5+)
Use standard ECMAScript decorators (Stage 3) instead of legacy experimentalDecorators
Use using declarations for explicit resource management with Disposable pattern instead of manual cleanup (TypeScript 5.2+)
Use with { type: "json" } for import attributes; avoid deprecated assert syntax (TypeScript 5.3/5.8+)
Use import type explicitly when importing types to ensure they are erased during compilation, respecting verbatimModuleSyntax flag
Use .ts, .mts, .cts extensions in import type statements (TypeScript 5.2+)
Use import type { Type } from "mod" with { "resolution-mode": "import" } for specific module resolution contexts (TypeScript 5.3+)
Use new iterator methods (map, filter, etc.) if targeting modern environments (TypeScript 5.6+)
Utilize new Set methods like union, intersection, etc., when available (TypeScript 5.5+)
Use Object.groupBy / Map.groupBy standard methods for grouping instead of external libraries (TypeScript 5.4+)
Use Promise.withResolvers() for creating promises with exposed resolve/reject functions (TypeScript 5.7+)
Use copying array methods (toSorted, toSpliced, with) for immutable array operations (TypeScript 5.2+)
Avoid accessing instance fields via super in classes (TypeScript 5....

Files:

  • packages/propel/src/empty-state/detailed-empty-state.tsx
  • packages/types/src/instance/base.ts
  • packages/propel/src/empty-state/assets/asset-types.ts
  • apps/web/ce/components/global/product-updates/changelog.tsx
  • apps/web/core/components/onboarding/steps/profile/root.tsx
  • packages/propel/src/empty-state/assets/vertical-stack/index.ts
  • apps/web/core/components/global/product-updates/fallback.tsx
  • packages/propel/src/empty-state/assets/asset-registry.tsx
  • packages/propel/src/empty-state/assets/vertical-stack/changelog.tsx
  • apps/web/ce/components/global/product-updates/header.tsx
  • apps/web/core/components/core/image-picker-popover.tsx
  • packages/propel/src/empty-state/assets/vertical-stack/constant.tsx
  • apps/web/core/components/global/product-updates/modal.tsx
🧠 Learnings (3)
📚 Learning: 2025-10-01T15:30:17.605Z
Learnt from: lifeiscontent
Repo: makeplane/plane PR: 7888
File: packages/propel/src/avatar/avatar.stories.tsx:2-3
Timestamp: 2025-10-01T15:30:17.605Z
Learning: In the makeplane/plane repository, avoid suggesting inline type imports (e.g., `import { Avatar, type TAvatarSize }`) due to bundler compatibility issues. Keep type imports and value imports as separate statements.

Applied to files:

  • apps/web/ce/components/global/product-updates/header.tsx
📚 Learning: 2025-10-21T17:22:05.204Z
Learnt from: lifeiscontent
Repo: makeplane/plane PR: 7989
File: apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/pages/(detail)/[pageId]/page.tsx:45-46
Timestamp: 2025-10-21T17:22:05.204Z
Learning: In the makeplane/plane repository, the refactor from useParams() to params prop is specifically scoped to page.tsx and layout.tsx files in apps/web/app (Next.js App Router pattern). Other components (hooks, regular client components, utilities) should continue using the useParams() hook as that is the correct pattern for non-route components.

Applied to files:

  • apps/web/ce/components/global/product-updates/header.tsx
  • apps/web/core/components/core/image-picker-popover.tsx
  • apps/web/core/components/global/product-updates/modal.tsx
📚 Learning: 2025-10-09T20:42:31.843Z
Learnt from: lifeiscontent
Repo: makeplane/plane PR: 7922
File: apps/admin/app/(all)/(dashboard)/ai/form.tsx:19-19
Timestamp: 2025-10-09T20:42:31.843Z
Learning: In the makeplane/plane repository, React types are globally available through TypeScript configuration. Type annotations like React.FC, React.ReactNode, etc. can be used without explicitly importing the React namespace. The codebase uses the modern JSX transform, so React imports are not required for JSX or type references.

Applied to files:

  • apps/web/core/components/core/image-picker-popover.tsx
  • apps/web/core/components/global/product-updates/modal.tsx
🧬 Code graph analysis (7)
packages/propel/src/empty-state/detailed-empty-state.tsx (3)
packages/propel/src/empty-state/types.ts (1)
  • BaseEmptyStateCommonProps (11-25)
packages/propel/src/empty-state/assets/asset-registry.tsx (1)
  • getDetailedAsset (123-134)
packages/propel/src/empty-state/assets/asset-types.ts (1)
  • DetailedAssetType (54-54)
apps/web/ce/components/global/product-updates/changelog.tsx (2)
apps/web/core/components/global/product-updates/fallback.tsx (1)
  • ProductUpdatesFallback (8-32)
packages/ui/src/loader.tsx (1)
  • Loader (34-34)
apps/web/core/components/global/product-updates/fallback.tsx (1)
packages/propel/src/empty-state/detailed-empty-state.tsx (1)
  • EmptyStateDetailed (8-67)
packages/propel/src/empty-state/assets/asset-registry.tsx (1)
packages/propel/src/empty-state/assets/vertical-stack/changelog.tsx (1)
  • ChangelogVerticalStackIllustration (4-183)
packages/propel/src/empty-state/assets/vertical-stack/changelog.tsx (1)
packages/propel/src/empty-state/assets/helper.tsx (2)
  • TIllustrationAssetProps (13-15)
  • ILLUSTRATION_COLOR_TOKEN_MAP (1-11)
packages/propel/src/empty-state/assets/vertical-stack/constant.tsx (1)
packages/propel/src/empty-state/assets/vertical-stack/changelog.tsx (1)
  • ChangelogVerticalStackIllustration (4-183)
apps/web/core/components/global/product-updates/modal.tsx (1)
apps/web/ce/components/global/product-updates/changelog.tsx (1)
  • ProductUpdatesChangelog (8-83)
⏰ 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). (2)
  • GitHub Check: Build and lint web apps
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (11)
packages/propel/src/empty-state/assets/asset-types.ts (1)

29-29: Type surface extension for VerticalStackAssetType looks consistent

Adding "changelog" to VerticalStackAssetType aligns with the new vertical‑stack illustration and registry wiring; no issues from a typing perspective.

apps/api/plane/license/api/views/instance.py (1)

178-179: Exposing is_self_managed in instance config is consistent with the new type

Wiring settings.IS_SELF_MANAGED into data["is_self_managed"] cleanly exposes the deployment mode to clients and matches the updated IInstanceConfig shape.

packages/types/src/instance/base.ts (1)

59-59: IInstanceConfig.is_self_managed matches the backend payload

Adding a required is_self_managed: boolean property keeps the shared type in sync with the API response and simplifies downstream usage (no need for optional checks at the type level).

apps/web/ce/components/global/product-updates/header.tsx (1)

2-2: Version label wiring via package.json remains straightforward

Importing packageJson here to render v{packageJson.version} is clear and keeps the header self‑contained; no issues spotted.

packages/propel/src/empty-state/assets/vertical-stack/index.ts (1)

5-5: Barrel export for changelog illustration is correctly added

Re‑exporting ./changelog here keeps the vertical‑stack asset surface consistent and discoverable.

packages/propel/src/empty-state/assets/vertical-stack/constant.tsx (1)

5-5: Changelog vertical-stack asset is registered consistently

The ChangelogVerticalStackIllustration import and its entry in VerticalStackAssetsMap follow the established pattern for other assets; looks good.

Also applies to: 37-40

packages/propel/src/empty-state/assets/asset-registry.tsx (1)

36-36: LGTM! Asset registration follows existing patterns.

The new ChangelogVerticalStackIllustration import and registry entry are correctly implemented and consistent with the existing asset system.

Also applies to: 84-84

packages/propel/src/empty-state/detailed-empty-state.tsx (1)

18-18: LGTM! Alignment prop implementation is clean and backward-compatible.

The new align prop with default value "start" maintains backward compatibility while enabling centered layouts. The conditional class application using cn() follows best practices.

Also applies to: 25-40

apps/web/core/components/global/product-updates/modal.tsx (1)

11-12: LGTM! Modal refactoring improves separation of concerns.

Delegating changelog rendering to the dedicated ProductUpdatesChangelog component simplifies the modal and improves maintainability.

Also applies to: 31-31

packages/propel/src/empty-state/assets/vertical-stack/changelog.tsx (1)

1-183: LGTM! SVG illustration component follows established patterns.

The ChangelogVerticalStackIllustration component correctly uses color tokens for theming and properly spreads props. The implementation is consistent with other illustration assets in the system.

apps/web/core/components/global/product-updates/fallback.tsx (1)

3-31: LGTM! Fallback component provides clear user guidance.

The component correctly renders variant-specific changelog URLs and provides a clear call-to-action. The implementation is straightforward and maintainable.

Comment on lines +28 to +30
# Self-hosted mode
IS_SELF_MANAGED = True

Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Hardcoded IS_SELF_MANAGED flag prevents dynamic deployment detection.

The IS_SELF_MANAGED flag is hardcoded to True, which prevents runtime detection of deployment type. If the same codebase serves both cloud and self-hosted deployments, this will incorrectly identify cloud instances as self-managed.

Consider making this configurable via environment variable:

-# Self-hosted mode
-IS_SELF_MANAGED = True
+# Self-managed mode
+IS_SELF_MANAGED = os.environ.get("IS_SELF_MANAGED", "1") == "1"

This allows cloud deployments to set IS_SELF_MANAGED=0 while self-hosted instances default to self-managed mode.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Self-hosted mode
IS_SELF_MANAGED = True
# Self-managed mode
IS_SELF_MANAGED = os.environ.get("IS_SELF_MANAGED", "1") == "1"
🤖 Prompt for AI Agents
In apps/api/plane/settings/common.py around lines 28-30 the IS_SELF_MANAGED flag
is hardcoded to True which prevents runtime deployment detection; change it to
read an environment variable (e.g., IS_SELF_MANAGED) with a sensible default of
True for self-hosted, parse common truthy/falsey values (like "1","true","yes"
=> True; "0","false","no" => False) and assign the resulting boolean to
IS_SELF_MANAGED so cloud deployments can override via environment without
changing code.

@sriramveeraghanta sriramveeraghanta merged commit 7c74d0a into preview Dec 3, 2025
5 of 7 checks passed
@sriramveeraghanta sriramveeraghanta deleted the feat-selfhosted-check branch December 3, 2025 10:23
ClarenceChen0627 pushed a commit to ClarenceChen0627/plane that referenced this pull request Dec 5, 2025
* feat: add in common py

* fix: update marketing consent screen based on is self managed flag

* improvement: enhance ImagePickerPopover with dynamic tab options based on Unsplash configuration

* refactor: product updates modal to include changelog

* [WEB-5290] feat: implement fallback for product updates changelog with loading state and error handling

---------

Co-authored-by: sriramveeraghanta <[email protected]>
ClarenceChen0627 pushed a commit to ClarenceChen0627/plane that referenced this pull request Dec 5, 2025
* feat: add in common py

* fix: update marketing consent screen based on is self managed flag

* improvement: enhance ImagePickerPopover with dynamic tab options based on Unsplash configuration

* refactor: product updates modal to include changelog

* [WEB-5290] feat: implement fallback for product updates changelog with loading state and error handling

---------

Co-authored-by: sriramveeraghanta <[email protected]>
ClarenceChen0627 pushed a commit to ClarenceChen0627/plane that referenced this pull request Dec 5, 2025
* feat: add in common py

* fix: update marketing consent screen based on is self managed flag

* improvement: enhance ImagePickerPopover with dynamic tab options based on Unsplash configuration

* refactor: product updates modal to include changelog

* [WEB-5290] feat: implement fallback for product updates changelog with loading state and error handling

---------

Co-authored-by: sriramveeraghanta <[email protected]>
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.

3 participants