GitHub Pull Requests logo

Backstage GitHub Pull Requests Plugin

Created by Roadie

GitHub Pull Requests are the way teams propose changes, review code, and merge work in GitHub. The Backstage GitHub Pull Requests plugin brings that flow into your developer portal. You can open a service page and see its open pull requests with the same query syntax you use on GitHub. You get a focused view in the place where you discover and operate your services. This cuts the need to jump between tools during daily work.

The plugin lists pull requests with filters and search. It shows simple stats that help you track throughput and review health. Things like average time to merge, merge to close ratio, average lines changed, average files changed, and the time from first commit to pull request creation. You can add a pull requests card to entity Overview pages. You can add cards to the homepage that surface review requests and your open pull requests.

Teams that use GitHub Enterprise can point the cards at their own host. These pieces make it easy to spot stuck reviews, unblock teammates, and keep cycle time moving. If your goal is fewer context switches and faster merges, this plugin fits well in a self hosted Backstage stack.

Pull requests for Backstage rendered inside a Backstage plugin.
The statistics widget is alongside, showing the average time to merge a PR.

Installation Instructions

These instructions apply to self-hosted Backstage only.

Install the frontend package

  1. From the Backstage app package
    Copy
    cd packages/app
  2. Add the plugin
    Copy
    yarn add @roadiehq/backstage-plugin-github-pull-requests

Register the ScmAuth API in the frontend

The plugin needs the ScmAuth API in the app. Add it to the app apis.

  1. Open packages app src apis.ts
  2. Add the default ScmAuth factory
Copy
// packages/app/src/apis.ts
import { ScmAuth } from '@backstage/integration-react';
import { createApiFactory, discoveryApiRef, fetchApiRef } from '@backstage/core-plugin-api';
// keep your other imports

export const apis = [
  // keep your existing factories

  ScmAuth.createDefaultApiFactory(),

  // keep your existing factories
];

Enable GitHub auth in app config

The plugin relies on the GitHub auth provider.

  1. Add a GitHub provider entry in app config
Copy
# app-config.yaml
auth:
  environment: development
  providers:
    github:
      development:
        clientId: ${GITHUB_CLIENT_ID}
        clientSecret: ${GITHUB_CLIENT_SECRET}
  1. Make sure the Sign In page enables GitHub
Copy
// packages/app/src/App.tsx
import React from 'react';
import { createApp } from '@backstage/app-defaults';
import { SignInPage } from '@backstage/core-components';

const app = createApp({
  components: {
    SignInPage: props => (
      <SignInPage {...props} provider="github" />
    ),
  },
});

export default app.createRoot();

Add the Pull Requests tab to service entities

  1. Open packages app src components catalog EntityPage.tsx
  2. Import the components
  3. Add a route under your service page
Copy
// packages/app/src/components/catalog/EntityPage.tsx
import React from 'react';
import { EntityLayout, EntitySwitch } from '@backstage/plugin-catalog';
import {
  EntityGithubPullRequestsContent,
  isGithubPullRequestsAvailable,
} from '@roadiehq/backstage-plugin-github-pull-requests';

// inside your serviceEntityPage content
const serviceEntityPage = (
  <EntityLayout>
    {/* other routes */}
    <EntityLayout.Route
      path="/pull-requests"
      title="Pull Requests"
      // Uncomment to only show when annotations are present
      // if={isGithubPullRequestsAvailable}
    >
      <EntityGithubPullRequestsContent />
    </EntityLayout.Route>
    {/* other routes */}
  </EntityLayout>
);

Run the app and open a service entity. You will see a Pull Requests tab at path pull-requests.

Add the overview card on service pages

  1. Open packages app src components catalog EntityPage.tsx
  2. Import the components
  3. Add the card to your overview section inside an EntitySwitch case
Copy
// packages/app/src/components/catalog/EntityPage.tsx
import React from 'react';
import { Grid } from '@material-ui/core';
import { EntitySwitch } from '@backstage/plugin-catalog';
import {
  EntityGithubPullRequestsOverviewCard,
  isGithubPullRequestsAvailable,
} from '@roadiehq/backstage-plugin-github-pull-requests';

// inside your overviewContent
const overviewContent = (
  <Grid container spacing={3}>
    <EntitySwitch>
      <EntitySwitch.Case if={isGithubPullRequestsAvailable}>
        <Grid item md={6}>
          <EntityGithubPullRequestsOverviewCard />
        </Grid>
      </EntitySwitch.Case>
    </EntitySwitch>
  </Grid>
);

Add the team card on group pages

  1. Open packages app src components catalog EntityPage.tsx
  2. Import the components
  3. Add the card to your group page layout
Copy
// packages/app/src/components/catalog/EntityPage.tsx
import React from 'react';
import { Grid } from '@material-ui/core';
import { EntitySwitch } from '@backstage/plugin-catalog';
import {
  EntityGithubGroupPullRequestsCard,
  isGithubTeamPullRequestsAvailable,
} from '@roadiehq/backstage-plugin-github-pull-requests';

// inside your group page content
const groupPage = (
  <Grid container spacing={3}>
    <EntitySwitch>
      <EntitySwitch.Case if={isGithubTeamPullRequestsAvailable}>
        <Grid item md={5} xs={12}>
          <EntityGithubGroupPullRequestsCard />
        </Grid>
      </EntitySwitch.Case>
    </EntitySwitch>
  </Grid>
);

Add the homepage cards

  1. Make sure you have a Home page component
  2. Open packages app src components home HomePage.tsx
  3. Import the components
  4. Add the cards to your grid
Copy
// packages/app/src/components/home/HomePage.tsx
import React from 'react';
import { Grid } from '@material-ui/core';
import {
  HomePageRequestedReviewsCard,
  HomePageYourOpenPullRequestsCard,
} from '@roadiehq/backstage-plugin-github-pull-requests';

export const HomePage = () => {
  return (
    <Grid container spacing={3}>
      <Grid item md={6} xs={12}>
        <HomePageRequestedReviewsCard />
      </Grid>

      <Grid item md={6} xs={12}>
        <HomePageYourOpenPullRequestsCard query="org:RoadieHQ is:pr" />
      </Grid>
    </Grid>
  );
};

For GitHub Enterprise you can pass a hostname prop

Copy
<HomePageRequestedReviewsCard hostname="ghe.mycompany.com" />
<HomePageYourOpenPullRequestsCard hostname="ghe.mycompany.com" />

Add a default search filter per entity

Add an annotation in the catalog file for the service. The plugin will apply this filter by default.

Copy
# catalog-info.yaml
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
  name: my-service
  annotations:
    roadie-backstage-pull-requests/default-filter: is:open is:pr author:app%2Fmy-bot
spec:
  type: service
  owner: my-team
  lifecycle: production

Backend install

This plugin does not ship a backend package. No backend plugin install is needed on either the legacy backend system or the new backend system. You only need a working GitHub auth provider in your Backstage backend as shown in the app config above.

Things to Know

Plugin Configuration Requirements

This plugin relies on the GitHub Authentication Provider for its access to GitHub.

Changelog

This changelog is produced from commits made to the GitHub Pull Requests plugin since 9 months 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.

Breaking changes

  • None

Features

  • Add support for GitHub Enterprise in Home page PR cards via hostname prop #1875 6 months ago

Bug fixes

  • Fix crash in GitHub Pull Requests Statistics card when a PR has no commits #2062 3 days ago
  • Fix negative Average Coding Time value in statistics card #1815 7 months ago

Improvements

  • Stop using repository API to get repo slug #2057 12 days ago

Maintenance

  • Upgrade to 1 40 #1952 2 months ago
  • Remove unused plugin dependencies #1847 6 months ago
  • Revert dependency update PR #1825 7 months ago
  • Update Backstage dependencies #1821 7 months ago
  • Update dependency in GitHub plugin packages #1801 8 months ago
  • Update actions and scaffolder packages #1794 8 months ago

Set up Backstage in minutes with Roadie