A few days ago I decided to use the Gitlab Feature Flags into my Angular project and, while I was reading the official documentation, I found very hard to understand how to implement it and how it works, so I decided to write an “How to”.
Feature Flags aka Feature Toggles as Martin Fowler explains:
Feature Toggles (often also refered to as Feature Flags) are a powerful technique, allowing teams to modify system behavior without changing code.
And more from Gitlab official documentation:
With Feature Flags, you can deploy your application’s new features to production in smaller batches. You can toggle a feature on and off to subsets of users, helping you achieve Continuous Delivery. Feature flags help reduce risk, allowing you to do controlled testing, and separate feature delivery from customer launch.
So, basically, feature flags helps you to control the rollout of a feature, or enable it only for a specific environment (like develop or testing env) or for a specific list of users.
Gitlab uses Unleash as feature toggles so you have to connect to it. For the backend everything is configured, so you only have to setup the unleash client, for the frontend (like Angular) you have to do some other steps.
Even if Gitlab Cloud provides Unleash, your application cannot connect directly to it (it will respond you with 401 --- Unauthorized), instead you should use an Unleash Proxy in front of Gitlab in order to communicate with it, so you will have this connection schema:
First of all you have to enable feature flags into Gitlab and it’s very easy to do: you can find it in Deployments > Feature Flags and then click on “New feature flag”.
Here you can configure your feature flag as you needs. I created one, called image tagging and I choosed a strategy to enable it to all users but only in development and testing environments.
Then you can click on “Create feature flag” and the easy part is done.
Now it’s time to configure Unleash Proxy, to do that you needs some info to consent Unleash to connect with Gitlab. Go to Feature Flags page in Gitlab and click on “Configure”. In the pop-up you have all information:
NB: regeneration of Instance ID will break the integration of Unleash Proxy, so if you have to change it remember to update your Proxy with the new one.
To run Unleash Proxy you can use a simple docker:
docker run \
-e UNLEASH_PROXY_SECRETS=my_secret_for_client \
-e UNLEASH_URL=https://gitlab.com/api/v4/feature_flags/unleash/1111111 \
-e UNLEASH_INSTANCE_ID=XXXXXXXX \
-e UNLEASH_API_TOKEN=YYYYYY \
-e UNLEASH_APP_NAME=development \
-p 3000:3000 \
unleashorg/unleash-proxy:0.4.0
With these enviroment variables:
For each environment you have to deploy a new Unleash Proxy.
Now you can run the docker and check if everything it’s works using this curl:
curl http://localhost:3000/proxy -H "Authorization: UNLEASH_PROXY_SECRETS"
Replace UNLEASH_PROXY_SECRETS with your secret and you will get a response like this:
{"toggles":[{"name":"image_tagging","enabled":true,"variant":{"name":"disabled","enabled":false}}]}
Here we are: connecting the Angular app with the Unleash Proxy.
Unfortunately Unleash doesn’t support Angular officially but you can still use the Javascript Proxy SDK. So you can install it with npm:
npm install unleash-proxy-client
To handle the feature flags and the connection to the proxy you can create an Angular Service like this:
import { Injectable } from '@angular/core';
import { IMutableContext, UnleashClient } from 'unleash-proxy-client';
@Injectable({
providedIn: 'root',
})
export class FeatureFlagService {
unleash = new UnleashClient({
url: `http://localhost:3000/proxy`, // url to Unleash Proxy
clientKey: `my_secret_for_client`, // secret used in docker env UNLEASH_PROXY_SECRETS
appName: `development`, // the appName used in docker env UNLEASH_APP_NAME
environment: `development`, // you can configure it easily in environment.ts and environment.prod.ts
});
constructor() {}
start(): void {
this.unleash.start();
}
stop(): void {
this.unleash.stop();
}
updateContext(contextObj: IMutableContext): void {
this.unleash.updateContext(contextObj);
}
isEnabled(feature: string): boolean {
return this.unleash.isEnabled(feature);
}
}
And start the Unleash polling in the app.component.ts
:
import { Component, OnInit } from '@angular/core';
import { FeatureFlagService } from 'src/app/shared/services/feature-flag.service';
@Component({
selector: 'app-root',
template: `<router-outlet></router-outlet>`,
styles: [],
})
export class AppComponent implements OnInit {
constructor(private readonly featureFlagService: FeatureFlagService) {}
ngOnInit(): void {
this.featureFlagService.start();
}
}
So, if you want to check if a feature is enabled (according with the strategy used) you can use it in this way:
import { Component, OnInit } from '@angular/core';
import { FeatureFlagService } from 'src/app/shared/services/feature-flag.service';
@Component({
selector: 'app-image',
templateUrl: 'image.component.html',
styles: [],
})
export class ImageComponent implements OnInit {
constructor(private readonly featureFlagService: FeatureFlagService) {}
ngOnInit(): void {
if (this.featureFlagService.isEnabled('image_tagging')) {
// Do something
} else {
// Do something else
}
}
}
In this way you can activate or deactivate features or you can control the rollout of some features, even provide new features to a part of testing team.
That’s all folks!
Featured image from Pros and how to use feature flags explained and explored.
How to build REST API in a few minute using Google Apigee and gRPC