From 84a7c5ded313ba7746c457763f0d7189df0e5aa4 Mon Sep 17 00:00:00 2001 From: "claude[bot]" <209825114+claude[bot]@users.noreply.github.com> Date: Thu, 30 Oct 2025 13:36:34 +0000 Subject: [PATCH 1/5] docs: add fetch_policy configuration option for git storage Add documentation for the fetch_policy configuration option that controls how Flipt handles connection-related issues when fetching from remote Git repositories. - Added fetch_policy to example configuration - Documented available policies: strict (default) and lenient - Added usage examples and production warning - Placed in Git Remotes section for better organization Co-authored-by: Mark Phelps --- docs/v2/configuration/storage.mdx | 33 +++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/docs/v2/configuration/storage.mdx b/docs/v2/configuration/storage.mdx index 7daa31a..d5d585f 100644 --- a/docs/v2/configuration/storage.mdx +++ b/docs/v2/configuration/storage.mdx @@ -79,6 +79,7 @@ storage: remote: "https://github.com/flipt-io/example.git" branch: "main" poll_interval: "30s" + fetch_policy: "strict" credentials: "github" backend: type: memory @@ -86,6 +87,38 @@ storage: This configuration will create a git storage backend with the identifier `staging` in memory and will sync flag state to and from the remote repository. +### Fetch Policy + +The `fetch_policy` configuration option controls how Flipt handles connection-related issues when attempting to fetch from a remote Git repository. + +#### Available Policies + +- **`strict`** (default): Flipt will fail and return an error if it encounters connection issues when trying to fetch from the remote repository. This ensures that any connectivity problems are immediately visible and must be resolved. + +- **`lenient`**: Flipt will continue operating even if connection issues prevent fetching from the remote repository. This allows Flipt to remain functional during temporary network issues or remote repository unavailability. + +#### Usage Example + +```yaml +storage: + production: + remote: "https://github.com/company/flags.git" + fetch_policy: "strict" # Fail fast on connection issues + backend: + type: local + path: "/var/lib/flipt" + + development: + remote: "https://github.com/company/flags.git" + fetch_policy: "lenient" # Continue operation during connection issues + backend: + type: memory +``` + + + In production environments, consider using `strict` to ensure that connectivity issues are detected and resolved promptly, preventing potential configuration drift between your remote repository and running Flipt instances. + + ### Conflict Resolution Conflicts can occur when syncing flag state to and from a remote repository. The conflict resolution strategy in Flipt v2 is currently rudimentary and we aim to improve this in future releases. From bf8ce065805bc28a798df9c1f332bff0a715cac5 Mon Sep 17 00:00:00 2001 From: "claude[bot]" <209825114+claude[bot]@users.noreply.github.com> Date: Thu, 30 Oct 2025 17:31:45 +0000 Subject: [PATCH 2/5] docs: add fetch_policy to configuration overview storage table Added fetch_policy configuration option to the v2 storage table with: - Description: Policy for handling connection issues when fetching from remote Git - Options: strict, lenient - Default: strict - Available since: v2.3.0 Co-authored-by: Mark Phelps --- docs/v2/configuration/overview.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/v2/configuration/overview.mdx b/docs/v2/configuration/overview.mdx index 2eefd82..26e4112 100644 --- a/docs/v2/configuration/overview.mdx +++ b/docs/v2/configuration/overview.mdx @@ -192,6 +192,7 @@ Storage configuration defines where and how Flipt persists feature flag data, in | storage.[id].ca_cert_bytes | The CA certificate bytes for the remote URL | | v2.0.0 | | storage.[id].ca_cert_path | The CA certificate path for the remote URL | | v2.0.0 | | storage.[id].insecure_skip_tls | Skip verifying the server's certificate chain (avoid in production) | false | v2.0.0 | +| storage.[id].fetch_policy | Policy for handling connection issues when fetching from remote Git (strict, lenient) | strict | v2.3.0 | | storage.[id].credentials | The id of the credentials to use for the remote URL | | v2.0.0 | #### Commit Signing From 8800ad1f025e88f3dc5f7aacf46b7676259d8e5e Mon Sep 17 00:00:00 2001 From: Mark Phelps <209477+markphelps@users.noreply.github.com> Date: Fri, 31 Oct 2025 14:38:30 -0400 Subject: [PATCH 3/5] chore: run prettier Signed-off-by: Mark Phelps <209477+markphelps@users.noreply.github.com> --- .github/workflows/ci.yml | 1 - .github/workflows/worker.yml | 8 +- docs.json | 34 +--- docs/reo.js | 4 +- docs/v1/authorization/overview.mdx | 2 - .../migration/launchdarkly/openfeature.mdx | 171 ++++++++++-------- docs/v2/configuration/overview.mdx | 24 +-- docs/v2/configuration/storage.mdx | 11 +- 8 files changed, 129 insertions(+), 126 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9099c14..ba5dd6b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,4 +21,3 @@ jobs: - name: Check for Broken Links run: npx -y mint broken-links - diff --git a/.github/workflows/worker.yml b/.github/workflows/worker.yml index fef0e3c..9d38070 100644 --- a/.github/workflows/worker.yml +++ b/.github/workflows/worker.yml @@ -22,7 +22,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: '20' + node-version: "20" - name: Install dependencies working-directory: ./worker @@ -36,16 +36,16 @@ jobs: # Deploy the worker to preview environment OUTPUT=$(npx wrangler deploy --config wrangler.jsonc --env preview 2>&1) echo "$OUTPUT" - + # Extract the deployed URL from the output # Look for the worker URL pattern PREVIEW_URL=$(echo "$OUTPUT" | grep -o 'https://docs-preview[^[:space:]]*' | head -1) - + # If not found, try a more general pattern if [ -z "$PREVIEW_URL" ]; then PREVIEW_URL=$(echo "$OUTPUT" | grep -o 'https://[^[:space:]]*workers.dev' | head -1) fi - + echo "Extracted preview URL: $PREVIEW_URL" echo "preview_url=$PREVIEW_URL" >> $GITHUB_OUTPUT diff --git a/docs.json b/docs.json index 5a9e015..82f8778 100644 --- a/docs.json +++ b/docs.json @@ -37,10 +37,7 @@ "group": "Pro Features", "tag": "NEW", "icon": "crown", - "pages": [ - "v2/pro", - "v2/licensing" - ] + "pages": ["v2/pro", "v2/licensing"] }, { "group": "Configuration", @@ -66,9 +63,7 @@ "v2/integration/overview", { "group": "Server-Side SDKs", - "pages": [ - "v2/integration/server/rest" - ] + "pages": ["v2/integration/server/rest"] }, "v2/integration/client", "v2/integration/openfeature" @@ -143,9 +138,7 @@ }, { "group": "Migration Guides", - "pages": [ - "v2/guides/migration/cloud/flipt-cloud-to-v2" - ] + "pages": ["v2/guides/migration/cloud/flipt-cloud-to-v2"] } ] }, @@ -153,9 +146,7 @@ "group": "Tooling", "icon": "hammer", "tag": "NEW", - "pages": [ - "v2/tooling/github-actions" - ] + "pages": ["v2/tooling/github-actions"] } ] }, @@ -185,10 +176,7 @@ "groups": [ { "group": "Overview", - "pages": [ - "v1/introduction", - "v1/concepts" - ] + "pages": ["v1/introduction", "v1/concepts"] }, { "group": "Use Cases", @@ -333,9 +321,7 @@ }, { "group": "Authorization", - "pages": [ - "v1/authorization/overview" - ] + "pages": ["v1/authorization/overview"] }, { "group": "Operations", @@ -362,9 +348,7 @@ "groups": [ { "group": "Overview", - "pages": [ - "v1/reference/overview" - ] + "pages": ["v1/reference/overview"] }, { "group": "Authentication", @@ -475,9 +459,7 @@ { "anchor": "Changelog", "icon": "clock", - "pages": [ - "v1/changelog/overview" - ] + "pages": ["v1/changelog/overview"] }, { "anchor": "Blog", diff --git a/docs/reo.js b/docs/reo.js index e1ed7a2..3ec99aa 100644 --- a/docs/reo.js +++ b/docs/reo.js @@ -1,6 +1,6 @@ !(function () { var e, t, n; - (e = "a9505926280f383"), + ((e = "a9505926280f383"), (t = function () { Reo.init({ clientID: "a9505926280f383" }); }), @@ -8,5 +8,5 @@ "https://static.reo.dev/" + e + "/reo.js"), (n.defer = !0), (n.onload = t), - document.head.appendChild(n); + document.head.appendChild(n)); })(); diff --git a/docs/v1/authorization/overview.mdx b/docs/v1/authorization/overview.mdx index d5c38d1..7c9c1ec 100644 --- a/docs/v1/authorization/overview.mdx +++ b/docs/v1/authorization/overview.mdx @@ -187,14 +187,12 @@ The `input.request` field contains information about the incoming request. This - `namespace`: The [namespace](/v1/concepts#namespaces) in Flipt of the resource being accessed. If no namespace is provided, the default namespace is used, or it is not applicable as the resource is not namespace scoped (e.g. authentication) - `resource`: The resource being accessed. This can be one of: - - `namespace`: Access to [namespace](/v1/concepts#namespaces) resources (e.g., listing or creating namespaces). - `flag`: Access to [flag](/v1/concepts#flags) resources and sub-resources (e.g., listing or creating flags, variants, rules or rollouts). - `segment`: Access to [segment](/v1/concepts#segments) resources and sub-resources (e.g., listing or creating segments, constraints or distributions). - `authentication`: Access to authentication resources (e.g., listing or creating client tokens). - `subject`: The (optional) nested subject of the request. This can be one of: - - `namespace`: Access to [namespace](/v1/concepts#namespaces) resources. - `flag`: Access to [flag](/v1/concepts#flags) resources. - `variant`: Access to flag [variant](/v1/concepts#variant-flags) resources. diff --git a/docs/v1/guides/migration/launchdarkly/openfeature.mdx b/docs/v1/guides/migration/launchdarkly/openfeature.mdx index 8e6805f..8374f76 100644 --- a/docs/v1/guides/migration/launchdarkly/openfeature.mdx +++ b/docs/v1/guides/migration/launchdarkly/openfeature.mdx @@ -149,11 +149,11 @@ In the LaunchDarkly SDK, here's how you fetch the value of a boolean flag: const booleanFlagValue = await ldClient.boolVariation( featureFlags.booleanFlag.key, context, - false + false, ); doSomethingDependingOnFeatureFlagValue( featureFlags.booleanFlag.key, - booleanFlagValue + booleanFlagValue, ); ``` @@ -165,8 +165,8 @@ ldClient .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.booleanFlag.key, - flagValue - ) + flagValue, + ), ); ``` @@ -180,8 +180,8 @@ ldClient .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.booleanFlag.key, - flagValue - ) + flagValue, + ), ); ``` @@ -193,8 +193,8 @@ ldClient .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.booleanFlag.key, - flagValue - ) + flagValue, + ), ); ``` @@ -210,8 +210,8 @@ ldClient .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.booleanFlag.key, - flagValue - ) + flagValue, + ), ); ``` @@ -223,8 +223,8 @@ client .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.booleanFlag.key, - flagValue - ) + flagValue, + ), ); ``` @@ -236,8 +236,8 @@ ldClient .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.booleanFlag.key, - flagValue - ) + flagValue, + ), ); ``` @@ -249,8 +249,8 @@ client .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.booleanFlag.key, - flagValue - ) + flagValue, + ), ); ``` @@ -262,8 +262,8 @@ ldClient .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.booleanFlag.key, - flagValue - ) + flagValue, + ), ); ``` @@ -275,8 +275,8 @@ client .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.booleanFlag.key, - flagValue - ) + flagValue, + ), ); ``` @@ -295,8 +295,8 @@ ldClient .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.stringFlag.key, - flagValue - ) + flagValue, + ), ); ``` @@ -306,11 +306,11 @@ or, using the async/await syntax: const stringFlagValue = await ldClient.stringVariation( featureFlags.stringFlag.key, context, - "red" + "red", ); doSomethingDependingOnFeatureFlagValue( featureFlags.stringFlag.key, - stringFlagValue + stringFlagValue, ); ``` @@ -324,8 +324,8 @@ ldClient .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.stringFlag.key, - flagValue - ) + flagValue, + ), ); ``` @@ -337,8 +337,8 @@ client .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.stringFlag.key, - flagValue - ) + flagValue, + ), ); ``` @@ -350,8 +350,8 @@ ldClient .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.stringFlag.key, - flagValue - ) + flagValue, + ), ); ``` @@ -363,8 +363,8 @@ client .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.stringFlag.key, - flagValue - ) + flagValue, + ), ); ``` @@ -376,8 +376,8 @@ ldClient .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.stringFlag.key, - flagValue - ) + flagValue, + ), ); ``` @@ -389,8 +389,8 @@ client .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.stringFlag.key, - flagValue - ) + flagValue, + ), ); ``` @@ -404,8 +404,8 @@ ldClient .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.numberFlag.key, - flagValue - ) + flagValue, + ), ); ``` @@ -415,11 +415,11 @@ or using the async/await syntax: const numberFlagValue = await ldClient.numberVariation( featureFlags.numberFlag.key, context, - 50 + 50, ); doSomethingDependingOnFeatureFlagValue( featureFlags.numberFlag.key, - numberFlagValue + numberFlagValue, ); ``` @@ -433,8 +433,8 @@ ldClient .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.numberFlag.key, - flagValue - ) + flagValue, + ), ); ``` @@ -446,8 +446,8 @@ client .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.numberFlag.key, - flagValue - ) + flagValue, + ), ); ``` @@ -459,8 +459,8 @@ ldClient .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.numberFlag.key, - flagValue - ) + flagValue, + ), ); ``` @@ -472,8 +472,8 @@ client .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.numberFlag.key, - flagValue - ) + flagValue, + ), ); ``` @@ -485,8 +485,8 @@ ldClient .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.numberFlag.key, - flagValue - ) + flagValue, + ), ); ``` @@ -498,8 +498,8 @@ client .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.numberFlag.key, - flagValue - ) + flagValue, + ), ); ``` @@ -517,7 +517,10 @@ You can call each of these functions with a promise call chain: ldClient .jsonVariation(featureFlags.jsonFlag.key, context, {}) .then((flagValue) => - doSomethingDependingOnFeatureFlagValue(featureFlags.jsonFlag.key, flagValue) + doSomethingDependingOnFeatureFlagValue( + featureFlags.jsonFlag.key, + flagValue, + ), ); ``` @@ -527,11 +530,11 @@ or using the async/await syntax: const jsonFlagValue = await ldClient.jsonVariation( featureFlags.jsonFlag.key, context, - {} + {}, ); doSomethingDependingOnFeatureFlagValue( featureFlags.jsonFlag.key, - jsonFlagValue + jsonFlagValue, ); ``` @@ -541,7 +544,10 @@ When migrating a `jsonVariation()` call to the OpenFeature SDK, ldClient .jsonVariation(featureFlags.jsonFlag.key, context, {}) .then((flagValue) => - doSomethingDependingOnFeatureFlagValue(featureFlags.jsonFlag.key, flagValue) + doSomethingDependingOnFeatureFlagValue( + featureFlags.jsonFlag.key, + flagValue, + ), ); ``` @@ -551,7 +557,10 @@ becomes client .getObjectValue(featureFlags.jsonFlag.key, {}, context) .then((flagValue) => - doSomethingDependingOnFeatureFlagValue(featureFlags.jsonFlag.key, flagValue) + doSomethingDependingOnFeatureFlagValue( + featureFlags.jsonFlag.key, + flagValue, + ), ); ``` @@ -561,7 +570,10 @@ When migrating a `variation()` call, ldClient .variation(featureFlags.jsonFlag.key, context, {}) .then((flagValue) => - doSomethingDependingOnFeatureFlagValue(featureFlags.jsonFlag.key, flagValue) + doSomethingDependingOnFeatureFlagValue( + featureFlags.jsonFlag.key, + flagValue, + ), ); ``` @@ -571,7 +583,10 @@ also becomes client .getObjectValue(featureFlags.jsonFlag.key, {}, context) .then((flagValue) => - doSomethingDependingOnFeatureFlagValue(featureFlags.jsonFlag.key, flagValue) + doSomethingDependingOnFeatureFlagValue( + featureFlags.jsonFlag.key, + flagValue, + ), ); ``` @@ -581,7 +596,10 @@ Finally, when migrating a `jsonVariationDetail()` call, ldClient .jsonVariationDetail(featureFlags.jsonFlag.key, context, {}) .then((flagValue) => - doSomethingDependingOnFeatureFlagValue(featureFlags.jsonFlag.key, flagValue) + doSomethingDependingOnFeatureFlagValue( + featureFlags.jsonFlag.key, + flagValue, + ), ); ``` @@ -591,7 +609,10 @@ becomes client .getObjectDetails(featureFlags.jsonFlag.key, {}, context) .then((flagValue) => - doSomethingDependingOnFeatureFlagValue(featureFlags.jsonFlag.key, flagValue) + doSomethingDependingOnFeatureFlagValue( + featureFlags.jsonFlag.key, + flagValue, + ), ); ``` @@ -649,8 +670,8 @@ try { } catch (error) { console.log( `Failed to connect to LaunchDarkly :( Here's what the error says: ${JSON.stringify( - error - )}` + error, + )}`, ); } ``` @@ -661,8 +682,8 @@ LaunchDarkly also allows listening to the `error` event that signals an abnormal ldClient.on("error", (error) => { console.log( `The LaunchDarkly client has encountered an error. Here are the details: ${JSON.stringify( - error - )}` + error, + )}`, ); }); ``` @@ -673,8 +694,8 @@ In OpenFeature SDK terms, the equivalent listener looks like this: OpenFeature.addHandler(ProviderEvents.Error, (error) => { console.log( `The OpenFeature client for LaunchDarkly has encountered an error. Here are the details: ${JSON.stringify( - error - )}` + error, + )}`, ); }); ``` @@ -689,7 +710,7 @@ ldClient.on("update", (keyObject) => { ldClient .variation(keyObject.key, context, false) .then((flagValue) => - doSomethingDependingOnFeatureFlagValue(keyObject.key, flagValue) + doSomethingDependingOnFeatureFlagValue(keyObject.key, flagValue), ); }); ``` @@ -699,15 +720,15 @@ The `update:key` listener is more specific and serves to receive configuration u ```javascript ldClient.on(`update:${featureFlags.booleanFlag.key}`, () => { console.log( - `Configuration of flag ${featureFlags.booleanFlag.key} has changed` + `Configuration of flag ${featureFlags.booleanFlag.key} has changed`, ); ldClient .variation(featureFlags.booleanFlag.key, context, false) .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.booleanFlag.key, - flagValue - ) + flagValue, + ), ); }); ``` @@ -719,7 +740,7 @@ OpenFeature.addHandler( ProviderEvents.ConfigurationChanged, async (_eventDetails) => { // your event handling code - } + }, ); ``` @@ -732,7 +753,7 @@ OpenFeature.addHandler( const changedFlag = _eventDetails.flagsChanged[0]; console.log(`Configuration of flag ${changedFlag} has changed`); const flagType = Object.values(featureFlags).find( - (x) => x.key === changedFlag + (x) => x.key === changedFlag, ).type; let flagValue; @@ -746,11 +767,11 @@ OpenFeature.addHandler( flagValue = await client.getObjectValue(changedFlag, null, context); } else { console.log( - "Something went awry: we don't know the type of the updated flag" + "Something went awry: we don't know the type of the updated flag", ); } doSomethingDependingOnFeatureFlagValue(changedFlag, flagValue); - } + }, ); ``` diff --git a/docs/v2/configuration/overview.mdx b/docs/v2/configuration/overview.mdx index 26e4112..2e46712 100644 --- a/docs/v2/configuration/overview.mdx +++ b/docs/v2/configuration/overview.mdx @@ -181,19 +181,19 @@ Server configuration controls how Flipt listens for and serves HTTP, HTTPS, and Storage configuration defines where and how Flipt persists feature flag data, including local and remote Git repositories. -| Property | Description | Default | Since | -| ------------------------------ | ------------------------------------------------------------------- | ------------------- | ------ | -| storage.[id].name | The canonical name of the storage instance | default | v2.0.0 | -| storage.[id].backend.type | The type of backend to use (options: memory, local) | memory | v2.0.0 | -| storage.[id].backend.path | The path to the local storage directory for git backend | temporary directory | v2.0.0 | -| storage.[id].remote | The remote URL to sync storage to/from | | v2.0.0 | -| storage.[id].branch | The branch to use for git backend | main | v2.0.0 | -| storage.[id].poll_interval | The interval to poll the git repository and ref for changes | 30s | v2.0.0 | -| storage.[id].ca_cert_bytes | The CA certificate bytes for the remote URL | | v2.0.0 | -| storage.[id].ca_cert_path | The CA certificate path for the remote URL | | v2.0.0 | -| storage.[id].insecure_skip_tls | Skip verifying the server's certificate chain (avoid in production) | false | v2.0.0 | +| Property | Description | Default | Since | +| ------------------------------ | ------------------------------------------------------------------------------------- | ------------------- | ------ | +| storage.[id].name | The canonical name of the storage instance | default | v2.0.0 | +| storage.[id].backend.type | The type of backend to use (options: memory, local) | memory | v2.0.0 | +| storage.[id].backend.path | The path to the local storage directory for git backend | temporary directory | v2.0.0 | +| storage.[id].remote | The remote URL to sync storage to/from | | v2.0.0 | +| storage.[id].branch | The branch to use for git backend | main | v2.0.0 | +| storage.[id].poll_interval | The interval to poll the git repository and ref for changes | 30s | v2.0.0 | +| storage.[id].ca_cert_bytes | The CA certificate bytes for the remote URL | | v2.0.0 | +| storage.[id].ca_cert_path | The CA certificate path for the remote URL | | v2.0.0 | +| storage.[id].insecure_skip_tls | Skip verifying the server's certificate chain (avoid in production) | false | v2.0.0 | | storage.[id].fetch_policy | Policy for handling connection issues when fetching from remote Git (strict, lenient) | strict | v2.3.0 | -| storage.[id].credentials | The id of the credentials to use for the remote URL | | v2.0.0 | +| storage.[id].credentials | The id of the credentials to use for the remote URL | | v2.0.0 | #### Commit Signing diff --git a/docs/v2/configuration/storage.mdx b/docs/v2/configuration/storage.mdx index d5d585f..3ed9de4 100644 --- a/docs/v2/configuration/storage.mdx +++ b/docs/v2/configuration/storage.mdx @@ -103,20 +103,23 @@ The `fetch_policy` configuration option controls how Flipt handles connection-re storage: production: remote: "https://github.com/company/flags.git" - fetch_policy: "strict" # Fail fast on connection issues + fetch_policy: "strict" # Fail fast on connection issues backend: type: local path: "/var/lib/flipt" - + development: remote: "https://github.com/company/flags.git" - fetch_policy: "lenient" # Continue operation during connection issues + fetch_policy: "lenient" # Continue operation during connection issues backend: type: memory ``` - In production environments, consider using `strict` to ensure that connectivity issues are detected and resolved promptly, preventing potential configuration drift between your remote repository and running Flipt instances. + In production environments, consider using `strict` to ensure that + connectivity issues are detected and resolved promptly, preventing potential + configuration drift between your remote repository and running Flipt + instances. ### Conflict Resolution From 4538a4b849db4093cdd821b76bf9c26f968bcdf9 Mon Sep 17 00:00:00 2001 From: Mark Phelps <209477+markphelps@users.noreply.github.com> Date: Fri, 31 Oct 2025 14:43:20 -0400 Subject: [PATCH 4/5] Chore: format again Signed-off-by: Mark Phelps <209477+markphelps@users.noreply.github.com> --- docs/reo.js | 4 +- docs/v1/authorization/overview.mdx | 2 + .../migration/launchdarkly/openfeature.mdx | 171 ++++++++---------- 3 files changed, 79 insertions(+), 98 deletions(-) diff --git a/docs/reo.js b/docs/reo.js index 3ec99aa..e1ed7a2 100644 --- a/docs/reo.js +++ b/docs/reo.js @@ -1,6 +1,6 @@ !(function () { var e, t, n; - ((e = "a9505926280f383"), + (e = "a9505926280f383"), (t = function () { Reo.init({ clientID: "a9505926280f383" }); }), @@ -8,5 +8,5 @@ "https://static.reo.dev/" + e + "/reo.js"), (n.defer = !0), (n.onload = t), - document.head.appendChild(n)); + document.head.appendChild(n); })(); diff --git a/docs/v1/authorization/overview.mdx b/docs/v1/authorization/overview.mdx index 7c9c1ec..d5c38d1 100644 --- a/docs/v1/authorization/overview.mdx +++ b/docs/v1/authorization/overview.mdx @@ -187,12 +187,14 @@ The `input.request` field contains information about the incoming request. This - `namespace`: The [namespace](/v1/concepts#namespaces) in Flipt of the resource being accessed. If no namespace is provided, the default namespace is used, or it is not applicable as the resource is not namespace scoped (e.g. authentication) - `resource`: The resource being accessed. This can be one of: + - `namespace`: Access to [namespace](/v1/concepts#namespaces) resources (e.g., listing or creating namespaces). - `flag`: Access to [flag](/v1/concepts#flags) resources and sub-resources (e.g., listing or creating flags, variants, rules or rollouts). - `segment`: Access to [segment](/v1/concepts#segments) resources and sub-resources (e.g., listing or creating segments, constraints or distributions). - `authentication`: Access to authentication resources (e.g., listing or creating client tokens). - `subject`: The (optional) nested subject of the request. This can be one of: + - `namespace`: Access to [namespace](/v1/concepts#namespaces) resources. - `flag`: Access to [flag](/v1/concepts#flags) resources. - `variant`: Access to flag [variant](/v1/concepts#variant-flags) resources. diff --git a/docs/v1/guides/migration/launchdarkly/openfeature.mdx b/docs/v1/guides/migration/launchdarkly/openfeature.mdx index 8374f76..8e6805f 100644 --- a/docs/v1/guides/migration/launchdarkly/openfeature.mdx +++ b/docs/v1/guides/migration/launchdarkly/openfeature.mdx @@ -149,11 +149,11 @@ In the LaunchDarkly SDK, here's how you fetch the value of a boolean flag: const booleanFlagValue = await ldClient.boolVariation( featureFlags.booleanFlag.key, context, - false, + false ); doSomethingDependingOnFeatureFlagValue( featureFlags.booleanFlag.key, - booleanFlagValue, + booleanFlagValue ); ``` @@ -165,8 +165,8 @@ ldClient .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.booleanFlag.key, - flagValue, - ), + flagValue + ) ); ``` @@ -180,8 +180,8 @@ ldClient .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.booleanFlag.key, - flagValue, - ), + flagValue + ) ); ``` @@ -193,8 +193,8 @@ ldClient .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.booleanFlag.key, - flagValue, - ), + flagValue + ) ); ``` @@ -210,8 +210,8 @@ ldClient .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.booleanFlag.key, - flagValue, - ), + flagValue + ) ); ``` @@ -223,8 +223,8 @@ client .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.booleanFlag.key, - flagValue, - ), + flagValue + ) ); ``` @@ -236,8 +236,8 @@ ldClient .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.booleanFlag.key, - flagValue, - ), + flagValue + ) ); ``` @@ -249,8 +249,8 @@ client .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.booleanFlag.key, - flagValue, - ), + flagValue + ) ); ``` @@ -262,8 +262,8 @@ ldClient .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.booleanFlag.key, - flagValue, - ), + flagValue + ) ); ``` @@ -275,8 +275,8 @@ client .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.booleanFlag.key, - flagValue, - ), + flagValue + ) ); ``` @@ -295,8 +295,8 @@ ldClient .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.stringFlag.key, - flagValue, - ), + flagValue + ) ); ``` @@ -306,11 +306,11 @@ or, using the async/await syntax: const stringFlagValue = await ldClient.stringVariation( featureFlags.stringFlag.key, context, - "red", + "red" ); doSomethingDependingOnFeatureFlagValue( featureFlags.stringFlag.key, - stringFlagValue, + stringFlagValue ); ``` @@ -324,8 +324,8 @@ ldClient .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.stringFlag.key, - flagValue, - ), + flagValue + ) ); ``` @@ -337,8 +337,8 @@ client .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.stringFlag.key, - flagValue, - ), + flagValue + ) ); ``` @@ -350,8 +350,8 @@ ldClient .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.stringFlag.key, - flagValue, - ), + flagValue + ) ); ``` @@ -363,8 +363,8 @@ client .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.stringFlag.key, - flagValue, - ), + flagValue + ) ); ``` @@ -376,8 +376,8 @@ ldClient .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.stringFlag.key, - flagValue, - ), + flagValue + ) ); ``` @@ -389,8 +389,8 @@ client .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.stringFlag.key, - flagValue, - ), + flagValue + ) ); ``` @@ -404,8 +404,8 @@ ldClient .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.numberFlag.key, - flagValue, - ), + flagValue + ) ); ``` @@ -415,11 +415,11 @@ or using the async/await syntax: const numberFlagValue = await ldClient.numberVariation( featureFlags.numberFlag.key, context, - 50, + 50 ); doSomethingDependingOnFeatureFlagValue( featureFlags.numberFlag.key, - numberFlagValue, + numberFlagValue ); ``` @@ -433,8 +433,8 @@ ldClient .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.numberFlag.key, - flagValue, - ), + flagValue + ) ); ``` @@ -446,8 +446,8 @@ client .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.numberFlag.key, - flagValue, - ), + flagValue + ) ); ``` @@ -459,8 +459,8 @@ ldClient .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.numberFlag.key, - flagValue, - ), + flagValue + ) ); ``` @@ -472,8 +472,8 @@ client .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.numberFlag.key, - flagValue, - ), + flagValue + ) ); ``` @@ -485,8 +485,8 @@ ldClient .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.numberFlag.key, - flagValue, - ), + flagValue + ) ); ``` @@ -498,8 +498,8 @@ client .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.numberFlag.key, - flagValue, - ), + flagValue + ) ); ``` @@ -517,10 +517,7 @@ You can call each of these functions with a promise call chain: ldClient .jsonVariation(featureFlags.jsonFlag.key, context, {}) .then((flagValue) => - doSomethingDependingOnFeatureFlagValue( - featureFlags.jsonFlag.key, - flagValue, - ), + doSomethingDependingOnFeatureFlagValue(featureFlags.jsonFlag.key, flagValue) ); ``` @@ -530,11 +527,11 @@ or using the async/await syntax: const jsonFlagValue = await ldClient.jsonVariation( featureFlags.jsonFlag.key, context, - {}, + {} ); doSomethingDependingOnFeatureFlagValue( featureFlags.jsonFlag.key, - jsonFlagValue, + jsonFlagValue ); ``` @@ -544,10 +541,7 @@ When migrating a `jsonVariation()` call to the OpenFeature SDK, ldClient .jsonVariation(featureFlags.jsonFlag.key, context, {}) .then((flagValue) => - doSomethingDependingOnFeatureFlagValue( - featureFlags.jsonFlag.key, - flagValue, - ), + doSomethingDependingOnFeatureFlagValue(featureFlags.jsonFlag.key, flagValue) ); ``` @@ -557,10 +551,7 @@ becomes client .getObjectValue(featureFlags.jsonFlag.key, {}, context) .then((flagValue) => - doSomethingDependingOnFeatureFlagValue( - featureFlags.jsonFlag.key, - flagValue, - ), + doSomethingDependingOnFeatureFlagValue(featureFlags.jsonFlag.key, flagValue) ); ``` @@ -570,10 +561,7 @@ When migrating a `variation()` call, ldClient .variation(featureFlags.jsonFlag.key, context, {}) .then((flagValue) => - doSomethingDependingOnFeatureFlagValue( - featureFlags.jsonFlag.key, - flagValue, - ), + doSomethingDependingOnFeatureFlagValue(featureFlags.jsonFlag.key, flagValue) ); ``` @@ -583,10 +571,7 @@ also becomes client .getObjectValue(featureFlags.jsonFlag.key, {}, context) .then((flagValue) => - doSomethingDependingOnFeatureFlagValue( - featureFlags.jsonFlag.key, - flagValue, - ), + doSomethingDependingOnFeatureFlagValue(featureFlags.jsonFlag.key, flagValue) ); ``` @@ -596,10 +581,7 @@ Finally, when migrating a `jsonVariationDetail()` call, ldClient .jsonVariationDetail(featureFlags.jsonFlag.key, context, {}) .then((flagValue) => - doSomethingDependingOnFeatureFlagValue( - featureFlags.jsonFlag.key, - flagValue, - ), + doSomethingDependingOnFeatureFlagValue(featureFlags.jsonFlag.key, flagValue) ); ``` @@ -609,10 +591,7 @@ becomes client .getObjectDetails(featureFlags.jsonFlag.key, {}, context) .then((flagValue) => - doSomethingDependingOnFeatureFlagValue( - featureFlags.jsonFlag.key, - flagValue, - ), + doSomethingDependingOnFeatureFlagValue(featureFlags.jsonFlag.key, flagValue) ); ``` @@ -670,8 +649,8 @@ try { } catch (error) { console.log( `Failed to connect to LaunchDarkly :( Here's what the error says: ${JSON.stringify( - error, - )}`, + error + )}` ); } ``` @@ -682,8 +661,8 @@ LaunchDarkly also allows listening to the `error` event that signals an abnormal ldClient.on("error", (error) => { console.log( `The LaunchDarkly client has encountered an error. Here are the details: ${JSON.stringify( - error, - )}`, + error + )}` ); }); ``` @@ -694,8 +673,8 @@ In OpenFeature SDK terms, the equivalent listener looks like this: OpenFeature.addHandler(ProviderEvents.Error, (error) => { console.log( `The OpenFeature client for LaunchDarkly has encountered an error. Here are the details: ${JSON.stringify( - error, - )}`, + error + )}` ); }); ``` @@ -710,7 +689,7 @@ ldClient.on("update", (keyObject) => { ldClient .variation(keyObject.key, context, false) .then((flagValue) => - doSomethingDependingOnFeatureFlagValue(keyObject.key, flagValue), + doSomethingDependingOnFeatureFlagValue(keyObject.key, flagValue) ); }); ``` @@ -720,15 +699,15 @@ The `update:key` listener is more specific and serves to receive configuration u ```javascript ldClient.on(`update:${featureFlags.booleanFlag.key}`, () => { console.log( - `Configuration of flag ${featureFlags.booleanFlag.key} has changed`, + `Configuration of flag ${featureFlags.booleanFlag.key} has changed` ); ldClient .variation(featureFlags.booleanFlag.key, context, false) .then((flagValue) => doSomethingDependingOnFeatureFlagValue( featureFlags.booleanFlag.key, - flagValue, - ), + flagValue + ) ); }); ``` @@ -740,7 +719,7 @@ OpenFeature.addHandler( ProviderEvents.ConfigurationChanged, async (_eventDetails) => { // your event handling code - }, + } ); ``` @@ -753,7 +732,7 @@ OpenFeature.addHandler( const changedFlag = _eventDetails.flagsChanged[0]; console.log(`Configuration of flag ${changedFlag} has changed`); const flagType = Object.values(featureFlags).find( - (x) => x.key === changedFlag, + (x) => x.key === changedFlag ).type; let flagValue; @@ -767,11 +746,11 @@ OpenFeature.addHandler( flagValue = await client.getObjectValue(changedFlag, null, context); } else { console.log( - "Something went awry: we don't know the type of the updated flag", + "Something went awry: we don't know the type of the updated flag" ); } doSomethingDependingOnFeatureFlagValue(changedFlag, flagValue); - }, + } ); ``` From 980f2f3267ed2754ea2181df527a17e0b879bc38 Mon Sep 17 00:00:00 2001 From: Mark Phelps <209477+markphelps@users.noreply.github.com> Date: Fri, 31 Oct 2025 14:45:41 -0400 Subject: [PATCH 5/5] chore: rm worker test workflow Signed-off-by: Mark Phelps <209477+markphelps@users.noreply.github.com> --- .github/workflows/worker.yml | 95 ------------------------------------ 1 file changed, 95 deletions(-) delete mode 100644 .github/workflows/worker.yml diff --git a/.github/workflows/worker.yml b/.github/workflows/worker.yml deleted file mode 100644 index 9d38070..0000000 --- a/.github/workflows/worker.yml +++ /dev/null @@ -1,95 +0,0 @@ -name: Test Worker Redirects - -on: - pull_request: - types: [opened, synchronize, reopened] - -jobs: - test: - runs-on: ubuntu-latest - permissions: - contents: read - deployments: write - pull-requests: write - - env: - CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} - CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} - - steps: - - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: "20" - - - name: Install dependencies - working-directory: ./worker - run: npm install - - # Deploy preview - - name: Deploy Worker Preview - id: deploy - working-directory: ./worker - run: | - # Deploy the worker to preview environment - OUTPUT=$(npx wrangler deploy --config wrangler.jsonc --env preview 2>&1) - echo "$OUTPUT" - - # Extract the deployed URL from the output - # Look for the worker URL pattern - PREVIEW_URL=$(echo "$OUTPUT" | grep -o 'https://docs-preview[^[:space:]]*' | head -1) - - # If not found, try a more general pattern - if [ -z "$PREVIEW_URL" ]; then - PREVIEW_URL=$(echo "$OUTPUT" | grep -o 'https://[^[:space:]]*workers.dev' | head -1) - fi - - echo "Extracted preview URL: $PREVIEW_URL" - echo "preview_url=$PREVIEW_URL" >> $GITHUB_OUTPUT - - - name: Run redirect tests - id: tests - run: | - set -euo pipefail - - BASE_URL="${{ steps.deploy.outputs.preview_url }}" - echo "Testing against preview URL: $BASE_URL" - - echo "Testing root → /v2/" - LOCATION=$(curl -s -o /dev/null -w "%{redirect_url}" $BASE_URL/) - test "$LOCATION" = "$BASE_URL/v2/" - - echo "Testing unversioned path → /v1/path" - LOCATION=$(curl -s -o /dev/null -w "%{redirect_url}" $BASE_URL/getting-started) - test "$LOCATION" = "$BASE_URL/v1/getting-started" - - echo "Testing already versioned path (/v1) → no redirect" - STATUS=$(curl -s -o /dev/null -w "%{http_code}" --max-redirs 0 $BASE_URL/v1/getting-started) - # Should not get a redirect (301/302), might get 404 or 522 since there's no backend - if [ "$STATUS" -eq 301 ] || [ "$STATUS" -eq 302 ]; then - echo "ERROR: /v1/ path should not redirect but got status $STATUS" - exit 1 - fi - echo "✓ Got status $STATUS (not a redirect)" - - echo "Testing already versioned path (/v2) → no redirect" - STATUS=$(curl -s -o /dev/null -w "%{http_code}" --max-redirs 0 $BASE_URL/v2/getting-started) - # Should not get a redirect (301/302), might get 404 or 522 since there's no backend - if [ "$STATUS" -eq 301 ] || [ "$STATUS" -eq 302 ]; then - echo "ERROR: /v2/ path should not redirect but got status $STATUS" - exit 1 - fi - echo "✓ Got status $STATUS (not a redirect)" - - echo "Testing excluded path (.css) → no redirect" - STATUS=$(curl -s -o /dev/null -w "%{http_code}" --max-redirs 0 $BASE_URL/styles.css) - # Should not get a redirect (301/302), might get 404 or 522 since there's no backend - if [ "$STATUS" -eq 301 ] || [ "$STATUS" -eq 302 ]; then - echo "ERROR: .css path should not redirect but got status $STATUS" - exit 1 - fi - echo "✓ Got status $STATUS (not a redirect)" - - echo "✅ All redirect tests passed!"