From ab99a8e5bc8e788c053bc675b8ff442696031d76 Mon Sep 17 00:00:00 2001 From: Lukas Reining Date: Wed, 22 May 2024 08:58:54 +0200 Subject: [PATCH] feat: add Flipt to playground (#293) --- .gitignore | 2 + README.md | 8 ++ config/flipt/flipt.yml | 79 +++++++++++++++++++ docker-compose.yaml | 32 ++++++++ package-lock.json | 37 +++++++++ package.json | 2 + packages/provider/src/lib/provider.service.ts | 15 +++- packages/ui/src/app/demos.tsx | 8 ++ packages/utils/src/lib/types.ts | 4 +- 9 files changed, 183 insertions(+), 4 deletions(-) create mode 100644 config/flipt/flipt.yml diff --git a/.gitignore b/.gitignore index 047dc302..50ca89ec 100644 --- a/.gitignore +++ b/.gitignore @@ -45,3 +45,5 @@ Thumbs.db # yalc stuff .yalc yalc.lock + +config/flipt/flipt.db diff --git a/README.md b/README.md index 99672fbe..f9dd1d69 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,7 @@ If you're brand new to feature flagging, consider reviewing the [What are featur - [Harness](#harness) - [LaunchDarkly](#launchdarkly) - [Flagsmith](#flagsmith) + - [Flipt](#flipt) - [Experimenting beyond the demo](#experimenting-beyond-the-demo) - [Evaluation context](#evaluation-context) - [Troubleshooting](#troubleshooting) @@ -420,6 +421,13 @@ Now that everything is configured, you should be able to [start the demo](#how-t Now that everything is configured, you should be able to [start the demo](#how-to-run-the-demo). Once it's started, select `flagsmith` from the provider list located at the bottom right of your screen. You should now be able to control the demo app via Flagsmith! +### Flipt + +[Flipt](https://www.flipt.io/) is an open-source feature management platform that's fully self-hosted. +It's easy to set up, has no seat limits, and is built for developers from scale-ups to enterprises. + +After [starting the demo](#how-to-run-the-demo), the Flipt UI is available at [http://localhost:8080](http://localhost:8080). + ## Experimenting beyond the demo ### Evaluation context diff --git a/config/flipt/flipt.yml b/config/flipt/flipt.yml new file mode 100644 index 00000000..15b37911 --- /dev/null +++ b/config/flipt/flipt.yml @@ -0,0 +1,79 @@ +version: "1.2" +namespace: default +flags: + - key: new-welcome-message + name: new-welcome-message + type: BOOLEAN_FLAG_TYPE + description: Controls the welcome banner message + enabled: true + rollouts: + - threshold: + percentage: 100 + value: true + - key: hex-color + name: hex-color + type: VARIANT_FLAG_TYPE + description: Controls the UI color + enabled: true + variants: + - key: c05543 + name: red + - key: 2f5230 + name: green + - key: 0d507b + name: blue + - key: d4ac0d + name: yellow + rules: + - segment: Signed-In-Users + distributions: + - variant: d4ac0d + rollout: 100 + - segment: All-Users + distributions: + - variant: 2f5230 + rollout: 100 + - key: use-remote-fib-service + name: use-remote-fib-service + type: BOOLEAN_FLAG_TYPE + description: Controls whether the remote fib service is used + enabled: true + rollouts: + - segment: + key: Signed-In-Users + value: true + - segment: + key: All-Users + - key: fib-algo + name: fib-algo + type: VARIANT_FLAG_TYPE + description: The algorithm to calculate the fibbonaci sequence + enabled: true + variants: + - key: binet + name: binet + - key: memo + name: memo + - key: loop + name: loop + - key: recursive + name: recursive + rules: + - segment: All-Users + distributions: + - variant: memo + rollout: 100 +segments: + - key: All-Users + name: All Users + description: All users are matched + match_type: ALL_MATCH_TYPE + - key: Signed-In-Users + name: Signed In Users + description: Users that are signed in + constraints: + - type: STRING_COMPARISON_TYPE + property: email + operator: suffix + value: '@faas.com' + match_type: ALL_MATCH_TYPE diff --git a/docker-compose.yaml b/docker-compose.yaml index 27abae34..d21071dc 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -23,6 +23,8 @@ services: - GO_FEATURE_FLAG_URL=http://go-feature-flag:1031 - GO_FEATURE_FLAG_WEB_URL=http://localhost:1031 - FIB_SERVICE_URL=http://fib-service:30001 + - FLIPT_URL=http://flipt:8080 + - FLIPT_WEB_URL=http://localhost:8080 - FIB_SERVICE_USER - FIB_SERVICE_PASS # Provider values come from the .env @@ -59,6 +61,7 @@ services: - OTEL_EXPORTER_JAEGER_AGENT_PORT=6832 - OTEL_SERVICE_NAME=fibonacci-service - GO_FEATURE_FLAG_URL=http://go-feature-flag:1031 + - FLIPT_URL=http://flipt:8080 - FIB_SERVICE_USER - FIB_SERVICE_PASS # Provider values come from the .env @@ -129,5 +132,34 @@ services: ports: - "1031:1031" + init_flipt: + image: docker.flipt.io/flipt/flipt:v1.42.0 + command: ["./flipt", "import", "/var/opt/flipt/flipt.yml"] + environment: + FLIPT_LOG_LEVEL: debug + FLIPT_META_TELEMETRY_ENABLED: false + FLIPT_DB_URL: "/var/opt/flipt/flipt.db" + volumes: + - "./config/flipt/flipt.yml:/var/opt/flipt/flipt.yml" + - "flipt:/var/opt/flipt" + + flipt: + image: docker.flipt.io/flipt/flipt:v1.42.0 + command: ["./flipt", "--force-migrate"] + environment: + FLIPT_CORS_ENABLED: true + FLIPT_TRACING_ENABLED: true + FLIPT_TRACING_EXPORTER: otlp + FLIPT_TRACING_OTLP_ENDPOINT: "otel-collector:4317" + FLIPT_DB_URL: "/var/opt/flipt/flipt.db" + volumes: + - "./config/flipt/flipt.yml:/var/opt/flipt/flipt.yml" + - "flipt:/var/opt/flipt" + depends_on: + - init_flipt + ports: + - '8080:8080' + volumes: flagd-flags: + flipt: diff --git a/package-lock.json b/package-lock.json index 48811790..f7bafd6e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,8 @@ "@openfeature/env-var-provider": "^0.3.0", "@openfeature/flagd-provider": "^0.13.0", "@openfeature/flagd-web-provider": "^0.7.0", + "@openfeature/flipt-provider": "^0.1.0", + "@openfeature/flipt-web-provider": "^0.1.0", "@openfeature/go-feature-flag-provider": "^0.7.0", "@openfeature/go-feature-flag-web-provider": "^0.2.0", "@openfeature/nestjs-sdk": "^0.1.3-experimental", @@ -2474,6 +2476,17 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@flipt-io/flipt": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@flipt-io/flipt/-/flipt-1.0.0.tgz", + "integrity": "sha512-DAEH5YVgjw2cLZBDTxgekEc8Zn2jlclLYlJdIC9cPE3wMSSudKgeWyh61GfQ3bV7YEz7LjPGhk1YBH+obeR4qw==", + "peer": true + }, + "node_modules/@flipt-io/flipt-client-browser": { + "version": "0.0.17", + "resolved": "https://registry.npmjs.org/@flipt-io/flipt-client-browser/-/flipt-client-browser-0.0.17.tgz", + "integrity": "sha512-AJxB1xXrK0r1HP3fKTYwcx1Zqwfj890XgsaO0pC4UGp434QyKZTeI386h9EvOHYrVYaZfpAuODjD0YnCM/dT3Q==" + }, "node_modules/@floating-ui/core": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.0.tgz", @@ -6293,6 +6306,30 @@ "@openfeature/web-sdk": "^1.0.0" } }, + "node_modules/@openfeature/flipt-provider": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@openfeature/flipt-provider/-/flipt-provider-0.1.0.tgz", + "integrity": "sha512-XPXJyd25E1UbO844pHUvfvPsk3j1rcCU5ZuC3aFSextq4ABPQWsp8gS8OFPKVbqzuqHqykhyaM02ah1sXdWmwQ==", + "dependencies": { + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@flipt-io/flipt": "^1.0.0", + "@openfeature/server-sdk": "^1.13.0" + } + }, + "node_modules/@openfeature/flipt-web-provider": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@openfeature/flipt-web-provider/-/flipt-web-provider-0.1.0.tgz", + "integrity": "sha512-VQ5qIKQ2B6qNbCZQfSvMAoF4mwAHQYZeh15v0ddiYzdXm5DhtAgURIuD3gz38t9BxUMMM2VQDjjmHiyyknhcmQ==", + "dependencies": { + "@flipt-io/flipt-client-browser": "^0.0.17", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@openfeature/web-sdk": "^1.0.0" + } + }, "node_modules/@openfeature/go-feature-flag-provider": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/@openfeature/go-feature-flag-provider/-/go-feature-flag-provider-0.7.0.tgz", diff --git a/package.json b/package.json index fb95551d..d833b89d 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,8 @@ "@openfeature/env-var-provider": "^0.3.0", "@openfeature/flagd-provider": "^0.13.0", "@openfeature/flagd-web-provider": "^0.7.0", + "@openfeature/flipt-provider": "^0.1.0", + "@openfeature/flipt-web-provider": "^0.1.0", "@openfeature/go-feature-flag-provider": "^0.7.0", "@openfeature/go-feature-flag-web-provider": "^0.2.0", "@openfeature/nestjs-sdk": "^0.1.3-experimental", diff --git a/packages/provider/src/lib/provider.service.ts b/packages/provider/src/lib/provider.service.ts index f322924d..4485954d 100644 --- a/packages/provider/src/lib/provider.service.ts +++ b/packages/provider/src/lib/provider.service.ts @@ -19,6 +19,7 @@ import { FLAGD_OFREP_PROVIDER_ID, FLAGD_PROVIDER_ID, FLAGSMITH_PROVIDER_ID, + FLIPT_PROVIDER_ID, GO_OFREP_PROVIDER_ID, GO_PROVIDER_ID, HARNESS_PROVIDER_ID, @@ -26,6 +27,7 @@ import { SPLIT_PROVIDER_ID, } from '@openfeature/utils'; import { OFREPProvider } from '@openfeature/ofrep-provider'; +import { FliptProvider } from '@openfeature/flipt-provider'; type ProviderMap = Record< ProviderId, @@ -114,14 +116,14 @@ export class ProviderService { endpoint: process.env.GO_FEATURE_FLAG_URL as string, }), available: () => !!process.env.GO_FEATURE_FLAG_URL, - url: process.env.GO_FEATURE_FLAG_WEB_URL as string + url: process.env.GO_FEATURE_FLAG_WEB_URL as string, }, [GO_OFREP_PROVIDER_ID]: { factory: () => { return new OFREPProvider({ baseUrl: process.env.GO_FEATURE_FLAG_URL as string }); }, available: () => !!process.env.GO_FEATURE_FLAG_URL, - url: process.env.GO_FEATURE_FLAG_WEB_URL as string + url: process.env.GO_FEATURE_FLAG_WEB_URL as string, }, [FLAGSMITH_PROVIDER_ID]: { factory: () => { @@ -162,6 +164,13 @@ export class ProviderService { available: () => !!process.env.HARNESS_KEY && !!process.env.HARNESS_KEY_WEB, webCredential: process.env.HARNESS_KEY_WEB, }, + [FLIPT_PROVIDER_ID]: { + factory: () => { + return new FliptProvider('default', { url: process.env.FLIPT_URL as string }); + }, + available: () => !!process.env.FLIPT_URL, + url: process.env.FLIPT_WEB_URL, + }, }; constructor() { @@ -206,7 +215,7 @@ export class ProviderService { host: p[1].host, port: p[1].port, tls: p[1].tls, - url: p[1].url + url: p[1].url, }; }); } diff --git a/packages/ui/src/app/demos.tsx b/packages/ui/src/app/demos.tsx index 7fc9bcfb..f44a5292 100644 --- a/packages/ui/src/app/demos.tsx +++ b/packages/ui/src/app/demos.tsx @@ -6,6 +6,7 @@ import { FLAGD_OFREP_PROVIDER_ID, FLAGD_PROVIDER_ID, FLAGSMITH_PROVIDER_ID, + FLIPT_PROVIDER_ID, GO_OFREP_PROVIDER_ID, GO_PROVIDER_ID, HARNESS_PROVIDER_ID, @@ -33,6 +34,7 @@ import { styledFib3rSteps } from './demos/fib3r/tour'; import { JSON_UPDATED } from './types'; import { getData } from './utils'; import { GoFeatureFlagWebProvider } from '@openfeature/go-feature-flag-web-provider'; +import { FliptWebProvider } from '@openfeature/flipt-web-provider'; type ProviderMap = Record< string, @@ -130,6 +132,12 @@ export class Demos extends Component< return new SplitWebProvider(this.getProviderCredential(SPLIT_PROVIDER_ID)); }, }, + [FLIPT_PROVIDER_ID]: { + factory: () => { + const fliptConfig = this.state.availableProviders.find((p) => p.id === FLIPT_PROVIDER_ID); + return new FliptWebProvider('default', { url: fliptConfig?.url }); + }, + }, }; constructor(props: Record) { diff --git a/packages/utils/src/lib/types.ts b/packages/utils/src/lib/types.ts index 5f9e05ec..05630702 100644 --- a/packages/utils/src/lib/types.ts +++ b/packages/utils/src/lib/types.ts @@ -8,6 +8,7 @@ export const SPLIT_PROVIDER_ID = 'split'; export const CB_PROVIDER_ID = 'cloudbees'; export const FLAGSMITH_PROVIDER_ID = 'flagsmith'; export const HARNESS_PROVIDER_ID = 'harness'; +export const FLIPT_PROVIDER_ID = 'flipt'; export type ProviderId = | typeof ENV_PROVIDER_ID @@ -19,7 +20,8 @@ export type ProviderId = | typeof SPLIT_PROVIDER_ID | typeof CB_PROVIDER_ID | typeof FLAGSMITH_PROVIDER_ID - | typeof HARNESS_PROVIDER_ID; + | typeof HARNESS_PROVIDER_ID + | typeof FLIPT_PROVIDER_ID; export interface AvailableProvider { id: ProviderId;