diff --git a/guides/get-going-with-gitops.mdx b/guides/get-going-with-gitops.mdx index 54dbb08..910585c 100644 --- a/guides/get-going-with-gitops.mdx +++ b/guides/get-going-with-gitops.mdx @@ -37,11 +37,11 @@ This endpoint happens to list out a bunch of strings in a JSON array. The sorting algorithm previously used was slow (Bubble Sort), and we want to try something new (Quicksort). While we feel confident in our implementation, we're going to practice caution and release the change behind a feature flag. -### The Application +### Structure If you want to follow along you can fork our [gitops guide - repository](https://github.com/flipt-io/flipt-gitops-guide). + repository](https://github.com/flipt-io/guides). ```bash @@ -426,7 +426,7 @@ The `flipt` binary has the sub-command `flipt validate`. This can be used to statically validate your Flipt feature configuration files. You can install this to run during a CI step and catch bugs before merging changes into `main`. -For GitHub, try our pre-built [Flipt Validate Action](https://github.com/marketplace/actions/flipt-validate-action). +For GitHub, try our pre-built [Flipt Setup Action](https://github.com/marketplace/actions/flipt-setup-action). @@ -588,12 +588,11 @@ At each commit, we could've fully recreated the configuration of our entire appl Now you have all the tools necessary to practice GitOps with your feature flags. -However, in production, your mileage may vary with the different backed types. -You might want to consider the `object` (and AWS S3 type) or the `oci` backend if your source Git repositories are large (we're working on a guide for that now). +You might want to consider the `object` or the `oci` backend if your source Git repositories are too large (we're working on a guide for that now). The declarative storage backends currently mandate that the UI is **read-only**. We've thoughts on how this could change in the future, but for now, this is a limitation. You always have your editor, Git and the SCMs (GitHub, Gitlab etc) for state management in the meantime. -Each of these backends work by polling their sources (git, local directory or object store) and the interval can be configured. +Each of these backends work by polling their sources (git, oci, local directory or object store) and the interval can be configured. Checkout the [Configuration: Storage: Declarative](/configuration/storage#declarative) for details on adjusting these intervals. diff --git a/guides/using-references.mdx b/guides/using-references.mdx new file mode 100644 index 0000000..f50733a --- /dev/null +++ b/guides/using-references.mdx @@ -0,0 +1,237 @@ +--- +title: Evaluating with References +description: Leveraging Flipt evaluation references for preview environments. +--- + +## What are References in Flipt? + +References are a way to pass additional information to Flipt during an evaluation request. This allows you to serve different flag states based on the reference when using our [Git backend](/configuration/storage#git). + +References are especially useful when using Flipt in preview environments. You can use references to serve a different Git branch for each preview environment keeping your main branch safe from untested configurations. + +## What are Preview Environments? + +Preview environments are a way to create a temporary environment for a pull request. This allows you to test your changes in a production-like environment before merging your code. This is especially useful for testing changes that require a full build and deploy cycle. + +In this guide, we're going to demonstrate how to leverage Flipt in preview environments to test changes in a production-like environment, without affecting your production users. + +## What You'll Learn + +In this guide you will learn how to: + +- ๐Ÿ Setup Flipt to work in a preview environment +- ๐Ÿš€ Create a preview environment for a pull request that modifies a feature flag in our [declarative format](/configuration/storage#flag-state-configuration) +- ๐ŸŒฒ Add, commit, and push the change to a preview branch +- ๐Ÿงช Test the change in the preview environment +- ๐ŸŽ‰ Merge the pull request and deploy the change to production + +## Our Example Application + +We're going to be making a change to our internal organization sales dashboard. This dashboard is made up of simple [React](https://reactjs.org/) frontend and a Go backend. The frontend is a single page application that makes API calls to the backend to fetch data. The backend is a **new** API that returns a list of sales performance data. The frontend will use this data to render a graph of our companies sales performance. + +Because this API is new and we're not sure how it will perform, we want to test it in a production-like environment before we merge it into our main branch. + +![Our example application without our new graph](/images/guides/using-references/dashboard-main.png) + +We already use Flipt in our production environment, and we want to be able to use the same instance without having to deploy a new Flipt specifically for our preview environments. + +We also make use of Flipt's GitOps integration to manage our feature flags in our Git repository. This allows us to manage our feature flags in a declarative format, and have them automatically synced to Flipt in the background. + + + If you're not familiar with Flipt's GitOps integration, check out our{" "} + GitOps guide for more information. + + +### Structure + +Our application lives in a directory committed to a Git repository. +For the example's sake, we assume the repository will be hosted on GitHub at `https://github.com/organization/repository.git`. + +The application is made up of three directories: + +- `cmd/api` - contains our Go backend API and loads the UI +- `ui` - contains our React frontend +- `pkg/performance` - contains our Flipt feature flag definition + + + If you want to follow along you can fork our [guide + repository](https://github.com/flipt-io/guides). + + +For the purpose of this guide, we'll mainly focus on the Go backend and the Flipt feature flag definition file. + +### Go Backend + +The purpose of our Go backend is two-fold: + +1. Serve our React frontend +2. Serve our new API + +Our new API is a simple HTTP endpoint that returns a list of sales performance data. + +Because we're good engineers, we want to make sure that our new API is performant before we merge it into our main branch. To do this, we're going to use Flipt to control access to our new API. + +The main bit of code that we want to guard is where we mount the `/api/performance` endpoint: + +```go cmd/api/main.go + http.HandleFunc("/api/performance", func(w http.ResponseWriter, r *http.Request) { + logger := slog.With( + slog.String("namespace", "performance"), + slog.String("flag", "showPerformanceHistory"), + ) + + // evaluate the showPerformanceHistory features flag + result, err := flipt.Evaluation().Boolean(r.Context(), &evaluation.EvaluationRequest{ + NamespaceKey: "performance", + FlagKey: "showPerformanceHistory", + EntityId: fmt.Sprintf("%x", rand.Intn(1000)), + Reference: os.Getenv("FLIPT_CLIENT_REFERENCE"), + }) + if err != nil { + logger.Error("evaluating flag", "error", err) + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + // if the flag is disabled we return that the endpoint cannot be found + if !result.Enabled { + logger.Debug("flag disabled") + http.Error(w, "path not found", http.StatusNotFound) + return + } + + if err := json.NewEncoder(w).Encode(&history); err != nil { + logger.Error("parsing json", "error", err) + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + }) +``` + +Here you can see that we're using Flipt's Go client to evaluate the `showPerformanceHistory` feature flag. If the flag is enabled, we return the sales performance data. + +Also of note, we're using the `FLIPT_CLIENT_REFERENCE` environment variable to pass in the reference to Flipt in the evaluation call. This is used to serve a different Git branch for each preview environment. We'll talk more about this later. + +### Flipt Feature Flag Definition + +Our feature flag definition is stored in the `pkg/performance` directory. This directory contains a single file called `features.yml`. This file contains the definition of our `showPerformanceHistory` feature flag. + +```yaml pkg/performance/features.yml +namespace: performance +flags: + - key: showPerformanceHistory + name: Show Performance History Graph + type: BOOLEAN_FLAG_TYPE + enabled: false +``` + + + You don't have to call your file `features.yml` and you can spread your flag + definitions across multiple files. Checkout our docs on [locating flag + state](/configuration/storage#locating-flag-state) to learn more. + + +## Creating Preview Environments + +For this guide, we're going to use [GitHub Actions](https://github.com/features/actions) to deploy our preview environments to [Koyeb](https://www.koyeb.com/). + +Koyeb has a nice tutorial on how to deploy a preview environment using GitHub Actions. You can find it [here](https://www.koyeb.com/tutorials/deploy-preview-environments-on-koyeb-for-github-pull-requests). + +To get our preview environments working with Flipt, we'll need some way of passing the Git branch name to Flipt. We can do this by setting the `FLIPT_CLIENT_REFERENCE` environment variable to the Git branch name. This will allow us to serve a different Git branch for each preview environment. + +To do this, we'll need to add a step to our GitHub Actions workflow that sets the `FLIPT_CLIENT_REFERENCE` environment variable to the Git branch name. + +```yaml +- name: Deploy the application to Koyeb + uses: koyeb/action-git-deploy@v1 + with: + app-name: "dashboard-app-preview-${{ github.head_ref }}" + service-name: ${{ github.head_ref }} + service-ports: "8081:http" + service-routes: "/:8081" + service-env: "FLIPT_CLIENT_REFERENCE=${{ github.head_ref }},FLIPT_ADDRESS=${{ secrets.FLIPT_ADDRESS }}" + docker: ghcr.io/flipt-io/dashboard-app:latest +``` + +Here we're also setting the `FLIPT_ADDRESS` environment variable to the address of our Flipt instance. This could also be configured in your application via a config file. + +## Enabling the Flag and Pushing to a Preview Branch + +Now that we have our preview environments setup, we can enable our feature flag and push our changes to a preview branch. + +To enable our feature flag, we'll need to update our `features.yml` file to set the `enabled` field to `true`. + +```yaml pkg/performance/features.yml +namespace: performance +flags: + - key: showPerformanceHistory + name: Show Performance History Graph + type: BOOLEAN_FLAG_TYPE + enabled: true +``` + +Now we can add, commit, and push our changes to a preview branch. + +```bash +git checkout -b feature/enable-performance-history +git add pkg/performance/features.yml +git commit -m "Enable performance history" +git push origin feature/enable-performance-history +``` + +We'll also need to create a pull request for our preview branch. This will trigger our GitHub Actions workflow and deploy our preview environment. + +## Testing the Change + +Before checking on our preview environment, let's take a look at our Flipt instance. We can see that our feature flag is still showing as disabled in the UI. + +This is because Flipt is configured to track the `main` branch of our Git repository by default, which is what it continues to show in the UI. + +![Our feature flag is still disabled in the UI](/images/guides/using-references/flag-disabled.png) + + + In an upcoming release, we'll be adding the ability to switch between + references in the UI. This will allow you to see the state of your feature + flags in each Git branch. + + +Now that our preview environment is deployed, we can test our new API. We can view our application deployed to Koyeb from the Koyeb dashboard. + +You can also view the application settings and see that the `FLIPT_CLIENT_REFERENCE` environment variable is set to the Git branch name. + +![Our application settings in Koyeb](/images/guides/using-references/koyeb-settings.png) + +Now we can click on the application URL to view our application. We can see that our new API is working and our graph is being rendered. ๐ŸŽ‰ + +This means our feature flag is enabled successfully in our preview environment. + +![Our example application with our new graph](/images/guides/using-references/dashboard-preview.png) + +## Merging the Pull Request + +Now that we've tested our new API in our preview environment, we can merge our pull request and deploy our changed flag definition to production. + +Note that we don't have to make any code changes in our production application. This is because our Flipt is already configured to track the HEAD of the `main` Git branch. This means that when we merge our pull request, our application will automatically start using the new flag state. + +![Our feature flag is now enabled in the UI](/images/guides/using-references/flag-enabled.png) + +## Recap + +In this guide, we learned how to use Flipt's GitOps integration and references to test changes in a production-like environment without affecting our production users. + +Using references allowed us to serve a different Git branch for each preview environment. This means that each of our developers can test their feature flag changes in a production-like environment without affecting other developers. + +There are likely many other ways to use references with Flipt. We'd love to hear how you're using references in your organization. + +### Further Considerations + +References are available for all of our GET API endpoints, (e.g. [`GET /api/v1/flags`](/reference/flags/list-flags)) as well as all of our evaluation endpoints (e.g. [`POST /evaluate/v1/boolean`](/reference/evaluation/boolean-evaluation)). + +We've also added support for references in all of our [server side REST SDKs](/integration/server/rest) and our [client side SDKs](/integration/client). + +References currently only work with Git, and our `git` backend, like all of the declarative storage backends, mandates that the UI is **read-only**. +We have thoughts on how this could change in the future, but for now, this is a limitation. +You always have your editor, Git and the SCMs (GitHub, Gitlab etc) for state management in the meantime. + +Flipt will automatically sync your feature flag definitions to Flipt in the background. Each of these backends work by polling their sources (git, oci, local directory or object store) and the interval can be configured. +Checkout the [Configuration: Storage: Declarative](/configuration/storage#declarative) for details on adjusting these intervals. diff --git a/images/guides/using-references/dashboard-main.png b/images/guides/using-references/dashboard-main.png new file mode 100644 index 0000000..48c0b60 Binary files /dev/null and b/images/guides/using-references/dashboard-main.png differ diff --git a/images/guides/using-references/dashboard-preview.png b/images/guides/using-references/dashboard-preview.png new file mode 100644 index 0000000..ca47336 Binary files /dev/null and b/images/guides/using-references/dashboard-preview.png differ diff --git a/images/guides/using-references/flag-disabled.png b/images/guides/using-references/flag-disabled.png new file mode 100644 index 0000000..09caf3d Binary files /dev/null and b/images/guides/using-references/flag-disabled.png differ diff --git a/images/guides/using-references/flag-enabled.png b/images/guides/using-references/flag-enabled.png new file mode 100644 index 0000000..e9ad171 Binary files /dev/null and b/images/guides/using-references/flag-enabled.png differ diff --git a/images/guides/using-references/koyeb-settings.png b/images/guides/using-references/koyeb-settings.png new file mode 100644 index 0000000..57e796c Binary files /dev/null and b/images/guides/using-references/koyeb-settings.png differ diff --git a/mint.json b/mint.json index dedf204..e6c6c5e 100644 --- a/mint.json +++ b/mint.json @@ -109,7 +109,10 @@ "pages": [ { "group": "User Guides", - "pages": ["guides/get-going-with-gitops"] + "pages": [ + "guides/get-going-with-gitops", + "guides/using-references" + ] }, { "group": "Operations Guides",