Buildkite is a CI and CD platform. It helps you run reliable pipelines for builds and releases. It is used by engineering teams to automate testing and delivery at scale.
The Buildkite plugin puts your pipelines inside Backstage. You can see recent builds for a service. You can watch step output in real time. You can open logs without leaving your portal. You can trigger a rebuild when needed. You can filter by branch or focus on the default branch to cut noise. When you need to go deeper, you can jump straight to the build in Buildkite.This fits a self hosted Backstage where teams want CI context next to ownership, docs, and on call info. Service owners get a fast view of build health during reviews and incidents. Platform teams can track deployments across environments from the same place. The result is fewer context switches and quicker feedback when something breaks or needs a rerun.
Installation Instructions
These instructions apply to self-hosted Backstage only. To use this plugin on Roadie, visit the docs.
Install the frontend package
yarn add @roadiehq/backstage-plugin-buildkite
Configure the proxy in app config
Add this to your app config. Keep the header value as an env var.
# app-config.yaml
proxy:
'/buildkite/api':
target: https://api.buildkite.com/v2/
headers:
Authorization: 'Bearer ${BUILDKITE_API_TOKEN}'
Add the plugin to the catalog entity page
Import the components. Place them on the entity page so users can see the builds.
// packages/app/src/components/catalog/EntityPage.tsx
import React from 'react';
import { EntitySwitch } from '@backstage/plugin-catalog';
import {
EntityBuildkiteContent,
isPluginApplicableToEntity as isBuildkiteAvailable,
} from '@roadiehq/backstage-plugin-buildkite';
// example content block for CI CD tab
export const cicdContent = (
<EntitySwitch>
<EntitySwitch.Case if={isBuildkiteAvailable}>
<EntityBuildkiteContent />
</EntitySwitch.Case>
</EntitySwitch>
);
To limit to the default branch only, pass the flag. An entity annotation can override this.
// packages/app/src/components/catalog/EntityPage.tsx
export const cicdContent = (
<EntitySwitch>
<EntitySwitch.Case if={isBuildkiteAvailable}>
<EntityBuildkiteContent defaultBranchOnly />
</EntitySwitch.Case>
</EntitySwitch>
);
Add this content block into your entity page layout so it renders in a tab or section that is visible in your app.
Annotate your catalog entities
Add the annotations to your catalog entity yaml.
metadata:
annotations:
buildkite.com/project-slug: exampleorg/exampleproject
# optional branch filter
buildkite.com/branch: 'main'
# optional default branch only switch
buildkite.com/default-branch-only: 'true'
Notes on behavior in code comments above
- If you set buildkite.com/branch the plugin shows only that branch
- If you set buildkite.com/default-branch-only to true the plugin shows only the default branch as reported by Buildkite
- The branch annotation takes priority over the default branch only flag and prop
Provide the Buildkite API token
Export the token in your shell so the proxy header can read it.
export BUILDKITE_API_TOKEN=xxx-xxx-xxx
You can also set it in your process manager or container env.
Backend setup for the proxy new backend system
Ensure the proxy backend plugin is added. This enables the proxy entries from your app config at the path under api proxy.
// packages/backend/src/index.ts
import { createBackend } from '@backstage/backend-defaults';
const backend = createBackend();
// other backend plugins
backend.add(import('@backstage/plugin-app-backend'));
// add the proxy backend plugin
backend.add(import('@backstage/plugin-proxy-backend'));
await backend.start();
No code changes are needed in this file beyond adding the proxy backend plugin if it is missing.
Backend setup for the proxy old backend system
If your backend uses the older pattern with createRouter and useHotMemoize, add the proxy plugin.
Create the proxy plugin wiring file if it is missing.
// packages/backend/src/plugins/proxy.ts
import { createRouter } from '@backstage/plugin-proxy-backend';
import { Logger } from 'winston';
import { PluginEnvironment } from '../types';
export default async function createPlugin(env: PluginEnvironment) {
return await createRouter({
config: env.config,
logger: env.logger as Logger,
discovery: env.discovery,
});
}
Wire it up in the backend index so it mounts under the api path.
// packages/backend/src/index.ts
import { createServiceBuilder } from '@backstage/backend-common';
import proxy from './plugins/proxy';
// other imports omitted for brevity
async function main() {
// create envs here as in your app
const apiRouter = Router();
// mount other routers
// mount the proxy at /api/proxy
apiRouter.use('/proxy', await proxy(proxyEnv));
await createServiceBuilder(module)
.addRouter('/api', apiRouter)
.start();
}
main().catch(err => {
process.exit(1);
});
This uses the same proxy config in app config shown earlier. The plugin will call the proxy under api proxy buildkite api.
Summary of what you should have
- Frontend package installed
- Proxy entries in app config
- Buildkite content added on the entity page
- Entity annotations present on services that use Buildkite
- Backend has the proxy plugin enabled either with the new backend method or the old backend method
Once in place, run your app as usual. The Buildkite tab or section should render on entities that have the annotations.
Things to Know
You might rebuild each build and track build progress with this plugin.
Changelog
This changelog is produced from commits made to the Buildkite 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.
Improvements
- Switch time handling to Luxon in the plugin. This can trim bundle size. It may slightly change date formatting in edge cases. #1759 merged 9 months ago
Maintenance
- Upgrade to Backstage 1.40 for compatibility with newer apps. #1952 merged 2 months ago
- Remove unused dependencies in the plugin. #1847 merged 7 months ago
- Update Backstage package versions to match recent core releases. #1728 merged 10 months ago
- Routine dependency update across plugins. #1684 merged 12 months ago
Breaking changes
- None noted
Set up Backstage in minutes with Roadie
Focus on using Backstage, rather than building and maintaining it.