Skip to content

Commit 440e2ff

Browse files
committed
feature flag
1 parent 0d61c9c commit 440e2ff

3 files changed

Lines changed: 29 additions & 1 deletion

File tree

apps/webapp/app/components/navigation/EnvironmentSelector.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ export function EnvironmentSelector({
5252
}, [navigation.location?.pathname]);
5353

5454
const hasStaging = project.environments.some((env) => env.type === "STAGING");
55+
const devBranchesEnabled = Boolean(organization.featureFlags?.devBranchesEnabled);
5556

5657
return (
5758
<Popover onOpenChange={(open) => setIsMenuOpen(open)} open={isMenuOpen}>
@@ -108,7 +109,14 @@ export function EnvironmentSelector({
108109
{project.environments
109110
.filter((env) => env.parentEnvironmentId === null)
110111
.map((env) => {
111-
if (isBranchableEnvironment(env)) {
112+
// DEVELOPMENT is only branchable in the UI when the org has the
113+
// multi-branch dev flag on. Without it, dev renders as a plain
114+
// selector button (the original behavior). PREVIEW is unaffected.
115+
const renderAsBranchable =
116+
isBranchableEnvironment(env) &&
117+
(env.type !== "DEVELOPMENT" || devBranchesEnabled);
118+
119+
if (renderAsBranchable) {
112120
const branchEnvironments = project.environments.filter(
113121
(e) => e.parentEnvironmentId === env.id
114122
);
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { prisma } from "~/db.server";
2+
import { FEATURE_FLAG } from "~/v3/featureFlags";
3+
import { makeFlag } from "~/v3/featureFlags.server";
4+
5+
export async function canAccessDevBranches(organizationId: string): Promise<boolean> {
6+
const org = await prisma.organization.findFirst({
7+
where: { id: organizationId },
8+
select: { featureFlags: true },
9+
});
10+
11+
const flag = makeFlag();
12+
return flag({
13+
key: FEATURE_FLAG.devBranchesEnabled,
14+
defaultValue: false,
15+
overrides: (org?.featureFlags as Record<string, unknown>) ?? {},
16+
});
17+
}

apps/webapp/app/v3/featureFlags.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export const FEATURE_FLAG = {
1616
computeMigrationFreePercentage: "computeMigrationFreePercentage",
1717
computeMigrationPaidPercentage: "computeMigrationPaidPercentage",
1818
computeMigrationRequireTemplate: "computeMigrationRequireTemplate",
19+
devBranchesEnabled: "devBranchesEnabled",
1920
} as const;
2021

2122
export const FeatureFlagCatalog = {
@@ -43,6 +44,8 @@ export const FeatureFlagCatalog = {
4344
// When on, migrated orgs build their compute template in required mode at deploy
4445
// (fails the deploy on error) instead of shadow. Strict boolean (see above).
4546
[FEATURE_FLAG.computeMigrationRequireTemplate]: z.boolean(),
47+
// Per-org access to development branches. Off unless enabled for the org.
48+
[FEATURE_FLAG.devBranchesEnabled]: z.coerce.boolean(),
4649
};
4750

4851
export type FeatureFlagKey = keyof typeof FeatureFlagCatalog;

0 commit comments

Comments
 (0)