Skip to content

Add support for multiple targets for the announcement banner#578

Open
heisbrot wants to merge 1 commit intomainfrom
feature/banner-target-support
Open

Add support for multiple targets for the announcement banner#578
heisbrot wants to merge 1 commit intomainfrom
feature/banner-target-support

Conversation

@heisbrot
Copy link
Copy Markdown
Contributor

@heisbrot heisbrot commented Mar 6, 2026

Summary by CodeRabbit

  • Refactor
    • Updated announcement targeting system from a simple flag to a flexible array-based deployment targeting approach, enabling more granular control over which deployments receive specific announcements.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 6, 2026

📝 Walkthrough

Walkthrough

The PR refactors announcement targeting from a simple boolean flag (isCloudOnly) to a flexible array-based model (targets), updating both the data structure in announcements.json and the corresponding filter logic in AnnouncementProvider.tsx to use the new targeting mechanism.

Changes

Cohort / File(s) Summary
Announcement Data Structure
announcements.json
Replaced isCloudOnly: false boolean field with targets: ["selfhosted"] string array to support flexible multi-target announcements.
Announcement Filtering Logic
src/contexts/AnnouncementProvider.tsx
Updated filtering logic to check if announcement targets includes "selfhosted" instead of relying on isCloudOnly and isNetBirdHosted; added TARGET constant and updated Announcement interface type definition.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • PR #538: Previously introduced the isCloudOnly filtering logic that this PR now replaces with the more flexible targets array-based approach.

Suggested reviewers

  • mlsmaycon

Poem

🐰 From boolean flags to flexible arrays,
Announcements now target in flexible ways,
Self-hosted takes center stage with pride,
A targeting system with room to guide! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the main change: replacing isCloudOnly with a targets field to support multiple announcement targets instead of a single boolean flag.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/banner-target-support

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
Copy Markdown

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/contexts/AnnouncementProvider.tsx`:
- Line 11: The provider currently hard-codes the runtime target (e.g.
"selfhosted") and no longer imports isNetBirdHosted(), causing cloud users to
see wrong banners and announcements with no targets to be dropped; restore
runtime detection by re-importing isNetBirdHosted from "@utils/netbird", compute
a runtimeTarget (e.g. runtimeTarget = isNetBirdHosted() ? "selfhosted" :
"cloud") inside AnnouncementProvider (the component that filters announcements),
and update the filter logic in whatever function/method filters announcements
(refer to the announcement filtering code around the existing targets check) so
that an announcement is kept if announcement.targets is undefined/empty OR
includes runtimeTarget (instead of comparing to a hard-coded string). Ensure all
occurrences that previously used the hard-coded "selfhosted" are replaced to use
runtimeTarget so cloud vs self-hosted splits behave the same as
DashboardLayout's isNetBirdHosted() branching.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: eb748f8b-6423-452f-8a84-d48f2ed215a9

📥 Commits

Reviewing files that changed from the base of the PR and between 9420214 and d91fc33.

📒 Files selected for processing (2)
  • announcements.json
  • src/contexts/AnnouncementProvider.tsx

} from "react";
import { usePermissions } from "@/contexts/PermissionsProvider";
import { isLocalDev, isNetBirdHosted } from "@utils/netbird";
import { isLocalDev } from "@utils/netbird";
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Restore runtime target detection before filtering.

Line 80 now matches against a hard-coded "selfhosted" target for every deployment, because the isNetBirdHosted() signal was removed at Line 11. That means cloud users will also see self-hosted banners, cloud-targeted banners can never render, and announcements without targets are silently dropped even though the field is optional on Line 34. src/layouts/DashboardLayout.tsx:27-46 still uses isNetBirdHosted() for the same cloud/self-hosted split, so the provider should derive the current target instead of hard-coding one.

Proposed fix
-import { isLocalDev } from "@utils/netbird";
+import { isLocalDev, isNetBirdHosted } from "@utils/netbird";
...
-const TARGET = "selfhosted";
+type AnnouncementTarget = "cloud" | "selfhosted";
...
 export interface Announcement extends AnnouncementVariant {
   tag: string;
   text: string;
   link?: string;
   linkText?: string;
   isExternal?: boolean;
   closeable: boolean;
-  targets?: string[];
+  targets?: AnnouncementTarget[];
 }
...
-    const filtered = raw.filter((a) => a.targets?.includes(TARGET));
+    const currentTarget: AnnouncementTarget = isNetBirdHosted()
+      ? "cloud"
+      : "selfhosted";
+    const filtered = raw.filter(
+      (a) => !a.targets?.length || a.targets.includes(currentTarget),
+    );

Also applies to: 18-18, 34-34, 80-80

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/contexts/AnnouncementProvider.tsx` at line 11, The provider currently
hard-codes the runtime target (e.g. "selfhosted") and no longer imports
isNetBirdHosted(), causing cloud users to see wrong banners and announcements
with no targets to be dropped; restore runtime detection by re-importing
isNetBirdHosted from "@utils/netbird", compute a runtimeTarget (e.g.
runtimeTarget = isNetBirdHosted() ? "selfhosted" : "cloud") inside
AnnouncementProvider (the component that filters announcements), and update the
filter logic in whatever function/method filters announcements (refer to the
announcement filtering code around the existing targets check) so that an
announcement is kept if announcement.targets is undefined/empty OR includes
runtimeTarget (instead of comparing to a hard-coded string). Ensure all
occurrences that previously used the hard-coded "selfhosted" are replaced to use
runtimeTarget so cloud vs self-hosted splits behave the same as
DashboardLayout's isNetBirdHosted() branching.

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.

1 participant