Merge pull request #1985 from appwrite/feat-feature-flags

Feat: Feature flags (simple)
This commit is contained in:
Darshan
2025-06-06 17:45:11 +05:30
committed by GitHub
8 changed files with 43 additions and 18 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
PUBLIC_CONSOLE_MODE=self-hosted
PUBLIC_CONSOLE_FEATURE_FLAGS=
PUBLIC_APPWRITE_MULTI_REGION=false
PUBLIC_APPWRITE_ENDPOINT=http://localhost/v1
PUBLIC_STRIPE_KEY=
PUBLIC_GROWTH_ENDPOINT=
+3
View File
@@ -78,6 +78,7 @@ jobs:
labels: ${{ steps.meta.outputs.labels }}
build-args: |
"PUBLIC_CONSOLE_MODE=cloud"
"PUBLIC_CONSOLE_FEATURE_FLAGS="sites,csv-import"
"PUBLIC_APPWRITE_MULTI_REGION=true"
"PUBLIC_GROWTH_ENDPOINT=${{ secrets.PUBLIC_GROWTH_ENDPOINT }}"
"PUBLIC_STRIPE_KEY=${{ secrets.PUBLIC_STRIPE_KEY_STAGE }}"
@@ -116,6 +117,7 @@ jobs:
build-args: |
"PUBLIC_CONSOLE_MODE=self-hosted"
"PUBLIC_APPWRITE_MULTI_REGION=false"
"PUBLIC_CONSOLE_FEATURE_FLAGS="sites,csv-import"
"PUBLIC_GROWTH_ENDPOINT=${{ secrets.PUBLIC_GROWTH_ENDPOINT }}"
publish-cloud-no-regions:
@@ -153,5 +155,6 @@ jobs:
build-args: |
"PUBLIC_CONSOLE_MODE=cloud"
"PUBLIC_APPWRITE_MULTI_REGION=false"
"PUBLIC_CONSOLE_FEATURE_FLAGS="sites,csv-import"
"PUBLIC_STRIPE_KEY=${{ secrets.PUBLIC_STRIPE_KEY_STAGE }}"
"PUBLIC_GROWTH_ENDPOINT=${{ secrets.PUBLIC_GROWTH_ENDPOINT }}"
+2
View File
@@ -21,6 +21,7 @@ ADD ./src /app/src
ADD ./static /app/static
ARG PUBLIC_CONSOLE_MODE
ARG PUBLIC_CONSOLE_FEATURE_FLAGS
ARG PUBLIC_APPWRITE_MULTI_REGION
ARG PUBLIC_APPWRITE_ENDPOINT
ARG PUBLIC_GROWTH_ENDPOINT
@@ -31,6 +32,7 @@ ARG SENTRY_RELEASE
ENV PUBLIC_APPWRITE_ENDPOINT=$PUBLIC_APPWRITE_ENDPOINT
ENV PUBLIC_GROWTH_ENDPOINT=$PUBLIC_GROWTH_ENDPOINT
ENV PUBLIC_CONSOLE_MODE=$PUBLIC_CONSOLE_MODE
ENV PUBLIC_CONSOLE_FEATURE_FLAGS=$PUBLIC_CONSOLE_FEATURE_FLAGS
ENV PUBLIC_APPWRITE_MULTI_REGION=$PUBLIC_APPWRITE_MULTI_REGION
ENV PUBLIC_STRIPE_KEY=$PUBLIC_STRIPE_KEY
ENV SENTRY_AUTH_TOKEN=$SENTRY_AUTH_TOKEN
+1
View File
@@ -24,6 +24,7 @@ async function main() {
log(bold().magenta('APPWRITE CONSOLE'));
log();
logEnv('CONSOLE MODE', env?.PUBLIC_CONSOLE_MODE);
logEnv('CONSOLE FEATURE FLAGS', env?.PUBLIC_CONSOLE_FEATURE_FLAGS);
logEnv('MULTI REGION', env?.PUBLIC_APPWRITE_MULTI_REGION);
logEnv('APPWRITE ENDPOINT', env?.PUBLIC_APPWRITE_ENDPOINT, 'relative');
logEnv('GROWTH ENDPOINT', env?.PUBLIC_GROWTH_ENDPOINT);
+2
View File
@@ -5,6 +5,7 @@ services:
context: .
args:
PUBLIC_CONSOLE_MODE: ${PUBLIC_CONSOLE_MODE}
PUBLIC_CONSOLE_FEATURE_FLAGS: ${PUBLIC_CONSOLE_FEATURE_FLAGS}
PUBLIC_APPWRITE_MULTI_REGION: ${PUBLIC_APPWRITE_MULTI_REGION}
PUBLIC_APPWRITE_ENDPOINT: ${PUBLIC_APPWRITE_ENDPOINT}
PUBLIC_GROWTH_ENDPOINT: ${PUBLIC_GROWTH_ENDPOINT}
@@ -21,6 +22,7 @@ services:
- build/
environment:
- PUBLIC_CONSOLE_MODE
- PUBLIC_CONSOLE_FEATURE_FLAGS
- PUBLIC_APPWRITE_MULTI_REGION
- PUBLIC_APPWRITE_ENDPOINT
- PUBLIC_GROWTH_ENDPOINT
+24
View File
@@ -0,0 +1,24 @@
import { env } from '$env/dynamic/public';
import type { Account } from './stores/user';
import type { Organization } from './stores/organization';
// Parse feature flags from env as a string array (exact match only)
const flagsRaw = (env.PUBLIC_CONSOLE_FEATURE_FLAGS ?? '').split(',');
function isFlagEnabled(name: string) {
// loose generic to allow safe access while retaining type safety
return <T extends { account?: Account; organization?: Organization }>(data: T) => {
const { account, organization } = data;
return !!(
flagsRaw.includes(name) ||
account?.prefs?.[`flags-${name}`] ||
organization?.prefs?.[`flags-${name}`]
);
};
}
export const flags = {
showSites: isFlagEnabled('sites'),
showCsvImport: isFlagEnabled('csv-import')
};
@@ -24,8 +24,7 @@
import { base } from '$app/paths';
import { IconPlus } from '@appwrite.io/pink-icons-svelte';
import type { Models } from '@appwrite.io/console';
import { organization } from '$lib/stores/organization';
import { APPWRITE_OFFICIALS_ORG, isCloud } from '$lib/system';
import { flags } from '$lib/flags';
export let data: PageData;
@@ -88,14 +87,6 @@
$isCsvImportInProgress = false;
}
}
/**
* Controls visibility of CSV Imports feature:
* - Shown if running on self-hosted
* - Shown on cloud only if the organization is Appwrite's.
* - Hidden on cloud for any non-Appwrite organization.
*/
$: showCsvImports = !isCloud || $organization.$id === APPWRITE_OFFICIALS_ORG;
</script>
{#key page.params.collection}
@@ -109,7 +100,7 @@
analyticsSource="database_documents" />
<Layout.Stack direction="row" alignItems="center" justifyContent="flex-end">
<ViewSelector view={data.view} {columns} hideView />
{#if showCsvImports}
{#if flags.showCsvImport(data)}
<Button
secondary
event={Click.DatabaseImportCsv}
@@ -2,8 +2,11 @@ import { Query, type Models } from '@appwrite.io/console';
import { sdk } from '$lib/stores/sdk';
import { getLimit, getPage, getSearch, getView, pageToOffset, View } from '$lib/helpers/load';
import { CARD_LIMIT, Dependencies } from '$lib/constants';
import { flags } from '$lib/flags';
export const load = async ({ url, depends, route, params, parent }) => {
const data = await parent();
export const load = async ({ url, depends, route, params }) => {
depends(Dependencies.SITES);
const page = getPage(url);
const search = getSearch(url);
@@ -11,11 +14,9 @@ export const load = async ({ url, depends, route, params }) => {
const offset = pageToOffset(page, limit);
const view = getView(url, route, View.Grid, View.Grid);
const sitesLive = false;
if (!sitesLive)
if (!flags.showSites(data)) {
return {
sitesLive,
sitesLive: false,
offset,
limit,
search,
@@ -25,9 +26,10 @@ export const load = async ({ url, depends, route, params }) => {
sites: []
} as Models.SiteList
};
}
return {
sitesLive,
sitesLive: true,
offset,
limit,
search,