Harness CI/CD helps teams build and ship software with repeatable pipelines. It covers builds, tests, approvals, and deployments. The platform focuses on visibility and control so engineers can move fast with guardrails in place.
The Harness CI/CD plugin brings that context into Backstage. It connects a Backstage service to a Harness project so you can see the latest pipeline executions without leaving your service page. You can view status, when a run started, how long it took, the commit behind it, and which triggers fired for CI. For CD you can see what services were deployed. If your project has many pipelines, you can narrow the view to the ones that matter for the service. You can re run failed executions from the same screen when enabled by your team.
Use the plugin to give service owners one place to check build and deploy health. Use it during incidents to trace a change from commit to production. Use it to watch trends in execution time while you refine pipelines. It fits teams that already run Harness and want their delivery signals next to docs, ownership, and scorecards in a self hosted Backstage. This keeps context close to the code and reduces the number of tools you need to open each day.
Installation Instructions
These instructions apply to self-hosted Backstage only. To use this plugin on Roadie, visit the docs.
Install the frontend package
- From the root of your Backstage app run
yarn add --cwd packages/app @harnessio/backstage-plugin-ci-cd
yarn install
Configure the backend proxy
The plugin calls Harness through the Backstage proxy. Add the proxy backend if your app does not have it yet.
New backend system
- Install the proxy backend package
yarn add --cwd packages/backend @backstage/plugin-proxy-backend
- Register the proxy backend in packages/backend/src/index.ts
// packages/backend/src/index.ts
import { createBackend } from '@backstage/backend-defaults';
const backend = createBackend();
// Registers the proxy backend using your app-config.yaml
backend.add(import('@backstage/plugin-proxy-backend'));
backend.start();
Legacy backend system
- Install the proxy backend package
yarn add --cwd packages/backend @backstage/plugin-proxy-backend
- Create the proxy plugin router
// 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,
});
}
- Mount the proxy router
// packages/backend/src/index.ts
import { createServiceBuilder } from '@backstage/backend-common';
import { LoggerService } from '@backstage/backend-plugin-api';
import { Router } from 'express';
import proxy from './plugins/proxy';
import { PluginEnvironment } from './types';
// createEnv is part of most Backstage templates
async function createEnv(name: string): Promise<PluginEnvironment> {
// your existing env creation code
throw new Error('implement createEnv as in your app template');
}
async function main() {
const env = await createEnv('development');
const apiRouter = Router();
apiRouter.use('/proxy', await proxy(env));
const service = createServiceBuilder(module)
.addRouter('/api', apiRouter);
await service.start();
}
main().catch(err => {
// your existing error handling
});
Configure app config
- Add the Harness proxy entry in app-config.yaml
# app-config.yaml
proxy:
'/harness/prod':
target: 'https://app.harness.io/'
headers:
'x-api-key': '<YOUR PAT OR SAT>'
Notes
The plugin uses this token to call Harness APIs. The token needs project view permission. It also needs pipeline view and execute permissions. For service accounts assign a role with these permissions.
If you use Harness on prem set target to your Harness URL.
- Optional Harness settings
# app-config.yaml
harness:
baseUrl: https://app.harness.io/
# set true to remove Run Pipeline from the UI
disableRunPipeline: false
Add the UI to the service page
Place the plugin content on the service entity page. You can replace an existing CI CD tab or add a new tab.
Use the existing CI CD tab when Harness is available
// packages/app/src/components/catalog/EntityPage.tsx
import React from 'react';
import { EntitySwitch, EntityLayout } from '@backstage/plugin-catalog';
import {
isHarnessCiCdAvailable,
EntityHarnessCiCdContent,
} from '@harnessio/backstage-plugin-ci-cd';
const cicdContent = (
<>
{/* your other CI CD cases */}
<EntitySwitch.Case if={isHarnessCiCdAvailable}>
<EntityHarnessCiCdContent />
</EntitySwitch.Case>
</>
);
// make sure cicdContent is used in your EntityLayout
export const serviceEntityPage = (
<EntityLayout>
{/* other routes */}
<EntityLayout.Route path="/ci-cd" title="CI CD">
{cicdContent}
</EntityLayout.Route>
</EntityLayout>
);
Add a dedicated Harness tab
// packages/app/src/components/catalog/EntityPage.tsx
import React from 'react';
import { EntityLayout } from '@backstage/plugin-catalog';
import {
isHarnessCiCdAvailable,
EntityHarnessCiCdContent,
} from '@harnessio/backstage-plugin-ci-cd';
export const serviceEntityPage = (
<EntityLayout>
{/* other routes */}
<EntityLayout.Route
path="/harness-ci-cd"
title="Harness CI CD"
if={isHarnessCiCdAvailable}
>
<EntityHarnessCiCdContent />
</EntityLayout.Route>
</EntityLayout>
);
Annotate your catalog entities
Add annotations to each service that uses Harness.
New annotations
Use pipeline and service URL maps. Keys become labels in the dropdown.
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: my-service
annotations:
harness.io/pipelines: |
labelA: https://app.harness.io/ng/#/account/<acc>/project/<proj>/pipelines/<pipe>/pipeline-studio
labelB: https://app.harness.io/ng/#/account/<acc>/project/<proj>/pipelines/<pipe2>/pipeline-studio
harness.io/services: |
labelA: https://app.harness.io/ng/#/account/<acc>/project/<proj>/services/<service>
labelB: https://app.harness.io/ng/#/account/<acc>/project/<proj>/services/<service2>
spec:
type: service
owner: team-a
Old annotations
If you still use the old style add these. The new annotations take priority when both exist.
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: my-service
annotations:
harness.io/project-url: https://app.harness.io/ng/#/account/<acc>/project/<proj>/details
# optional
# harness.io/ci-pipelineIds: <pipelineId1,pipelineId2>
# harness.io/cd-serviceId: <serviceId>
spec:
type: service
owner: team-a
Where you will see it
Open a service entity that has the annotations. You will see Harness executions in the CI CD tab you configured or in the Harness CI CD tab if you added a new route. The view shows recent executions with status, start time, duration, triggers for CI, and deployed services for CD. You can enable or disable run pipeline in app config.
Changelog
This changelog is produced from commits made to the Harness CI/CD plugin since a year ago, and based on the code located here. It may not contain information about all commits. Releases and version bumps are intentionally omitted. This changelog is generated by AI.
Bug Fixes
- Fix annotation in Harness CI CD plugin PR #154 merged 10 months ago
Set up Backstage in minutes with Roadie
Focus on using Backstage, rather than building and maintaining it.