Harness Feature Flags logo

Backstage Harness Feature Flags Plugin

Created by Harness

Harness Feature Flags lets you control releases with toggles. You can turn features on or off without a deploy. You can target specific environments or user groups. This reduces risk during rollouts. It also gives you a clean way to run experiments or handle incidents fast.

The Backstage plugin brings those flags into your portal. For each service, you can see every flag from the connected Harness project. You get the current state, the type, the environment, and recent change history. You can filter by environment to cut noise. This keeps the team focused on what matters for a given service. It removes the extra clicks of jumping between tools.

The plugin is useful in daily work. Before a release, engineers can verify the right flags are set. During a gradual rollout, the team can track status from the same place they manage the service. If something goes wrong, you can flip a kill switch fast. Product and QA get clear visibility as well. It fits into a self hosted Backstage so flags line up with the services your team owns. The result is simple visibility where you already work.

Installation Instructions

These instructions apply to self-hosted Backstage only.

Install the frontend package

Run this from the root of your Backstage app

Copy
yarn add --cwd packages/app @harnessio/backstage-plugin-feature-flags
yarn install

Enable the proxy in the backend

The plugin uses the Backstage proxy. Many apps already have it enabled. If not, add it.

New backend system

Add the dependency

Copy
yarn add --cwd packages/backend @backstage/plugin-proxy-backend

Register the proxy plugin

Copy
// packages/backend/src/index.ts

import { createBackend } from '@backstage/backend-defaults';
import { proxyPlugin } from '@backstage/plugin-proxy-backend';

const backend = createBackend();
backend.add(proxyPlugin());
backend.start();

Legacy backend system

Add the dependency

Copy
yarn add --cwd packages/backend @backstage/plugin-proxy-backend

Create the proxy plugin file

Copy
// packages/backend/src/plugins/proxy.ts

import { createRouter } from '@backstage/plugin-proxy-backend';
import { Router } from 'express';
import { PluginEnvironment } from '../types';

export default async function createPlugin(
  env: PluginEnvironment,
): Promise<Router> {
  return await createRouter({
    logger: env.logger,
    config: env.config,
    discovery: env.discovery,
    tokenManager: env.tokenManager,
  });
}

Wire it up in the backend

Copy
// packages/backend/src/index.ts

import proxy from './plugins/proxy';

// inside main function where other routers are added
apiRouter.use('/proxy', await proxy(env));

Add proxy config for Harness

Add this in your app config. Put your token value for the header. Use your Harness on prem URL in target if needed.

Copy
# app-config.yaml

proxy:
  '/harness':
    target: 'https://app.harness.io/'
    headers:
      'x-api-key': '${HARNESS_API_KEY}'

You can pass the token with an env var

Copy
HARNESS_API_KEY=your_token_value yarn dev

Optional Harness base URL

Only add this if you use a custom Harness URL

Copy
# app-config.yaml

harness:
  baseUrl: https://app.harness.io/

Add the Feature Flags tab to the service page

Edit the service entity page. Import the components. Add a new route so users can open the tab.

Copy
// packages/app/src/components/catalog/EntityPage.tsx

import React from 'react';
import { EntityLayout, EntitySwitch } from '@backstage/plugin-catalog';
import { EmptyState } from '@backstage/core-components';
import { Button } from '@material-ui/core';
import {
  isHarnessFeatureFlagAvailable,
  EntityHarnessFeatureFlagContent,
} from '@harnessio/backstage-plugin-feature-flags';

const featureFlagList = (
  <EntitySwitch>
    <EntitySwitch.Case if={isHarnessFeatureFlagAvailable}>
      <EntityHarnessFeatureFlagContent />
    </EntitySwitch.Case>

    <EntitySwitch.Case>
      <EmptyState
        title="No Feature Flags available for this entity"
        missing="info"
        description="You need to add an annotation to your component if you want to enable Feature Flags for it. You can read more about annotations in Backstage by clicking the button below."
        action={
          <Button
            variant="contained"
            color="primary"
            href="https://backstage.io/docs/features/software-catalog/well-known-annotations"
          >
            Read more
          </Button>
        }
      />
    </EntitySwitch.Case>
  </EntitySwitch>
);

export const serviceEntityPage = (
  <EntityLayout>
    {/* other routes */}
    <EntityLayout.Route path="/feature-flag" title="Feature Flags">
      {featureFlagList}
    </EntityLayout.Route>
  </EntityLayout>
);

Users will see a Feature Flags tab on each service page.

Add the required entity annotation

Add the Harness project URL to the catalog info for each service that should show Feature Flags.

Copy
# catalog-info.yaml

apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
  name: my-service
  annotations:
    harness.io/project-url: https://app.harness.io/ng/account/<accountId>/project/<projectId>/overview
    # optional
    # harness.io/ci-pipelineIds: pipelineId1,pipelineId2
    # harness.io/cd-serviceId: myServiceId
spec:
  type: service
  owner: team
  lifecycle: production

That is it. The frontend reads the annotation. The backend proxy forwards requests to Harness using the token you set in the config.

Changelog

The Harness Feature Flags plugin has not seen any significant changes since a year ago.

Set up Backstage in minutes with Roadie