GitHub Codespaces logo

Backstage GitHub Codespaces Plugin

Created by Aditya Singhal - Lab45

GitHub Codespaces gives you a ready to code environment in the cloud. It uses dev containers so every project opens with the right tools. You can start in the browser or connect from your desktop IDE. It is tied to your GitHub repo so you spin up a clean workspace fast.This Backstage plugin brings that flow into the catalog. It signs you in with GitHub then shows your codespaces.

You can see codespaces for the current entity or for its repository. You can start a fresh codespace with a display name that matches the entity. You can point the plugin at a custom dev container path through a catalog annotation. It is listed in the Backstage plugin directory.

Common use cases include faster onboarding for new services. Click from a service page to open a preconfigured workspace. Jump into a clean environment to fix a bug or review a pull request without local setup. Teams that rely on dev containers can standardize how developers start work and cut context switching.

Installation Instructions

These instructions apply to self-hosted Backstage only.

Configure GitHub OAuth

  1. Create a GitHub OAuth App in your org. Set the callback URL to http://localhost:7007/api/auth/github/handler/frame

  2. Set the client id and client secret as environment variables for the backend process

Copy
# in your backend environment
export AUTH_GITHUB_CLIENT_ID=your_client_id
export AUTH_GITHUB_CLIENT_SECRET=your_client_secret
  1. Add the required annotations to your catalog entities. This lets the plugin find the repo and an optional custom devcontainer file
Copy
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
  name: backstage
  description: backstage.io
  annotations:
    github.com/project-slug: 'backstage/backstage'
    # optional custom devcontainer path
    github.com/devcontainer-path: .devcontainer/devcontainer.json
spec:
  type: website
  lifecycle: production
  owner: user:guest

Install the plugin package

  1. Add the frontend package to your Backstage app package
Copy
# from your Backstage root
yarn add --cwd packages/app @adityasinghal26/plugin-github-codespaces

Add Codespaces to your entity pages

  1. Open packages/app/src/components/catalog/EntityPage.tsx

  2. Import the plugin components

Copy
import React from 'react';
import { Grid } from '@mui/material';
import { EntityLayout, EntitySwitch } from '@backstage/plugin-catalog';
import {
  EntityGithubCodespacesWidget,
  EntityGithubCodespacesCard,
  EntityGithubCodespacesContent,
  EntityGithubCodespacesRepoContent,
  isGithubCodespacesAvailable,
} from '@adityasinghal26/plugin-github-codespaces';
  1. Add a tab with Codespaces content filtered by entity and by repository
Copy
// create the Codespaces tab content
const codespacesContent = (
  <>
    {/* list codespaces filtered by entity name */}
    <EntitySwitch>
      <EntitySwitch.Case if={isGithubCodespacesAvailable}>
        <Grid item xs={12}>
          <EntityGithubCodespacesContent />
        </Grid>
      </EntitySwitch.Case>
    </EntitySwitch>

    {/* list codespaces filtered by project repository */}
    <EntitySwitch>
      <EntitySwitch.Case if={isGithubCodespacesAvailable}>
        <Grid item xs={12}>
          <EntityGithubCodespacesRepoContent />
        </Grid>
      </EntitySwitch.Case>
    </EntitySwitch>
  </>
);
  1. Add the overview widget and card to your overview layout
Copy
// you can reuse this on multiple entity pages
const overviewContent = (
  <Grid container spacing={3} alignItems="stretch">
    {/* other grids */}

    {/* start codespace widget */}
    <EntitySwitch>
      <EntitySwitch.Case if={e => Boolean(isGithubCodespacesAvailable(e))}>
        <Grid item md={6} xs={12}>
          <EntityGithubCodespacesWidget />
        </Grid>
      </EntitySwitch.Case>
    </EntitySwitch>

    {/* start and list codespace card
       set enableStart to true to show the start button */}
    <EntitySwitch>
      <EntitySwitch.Case if={e => Boolean(isGithubCodespacesAvailable(e))}>
        <Grid item md={6} xs={12}>
          <EntityGithubCodespacesCard enableStart={true} />
        </Grid>
      </EntitySwitch.Case>
    </EntitySwitch>
  </Grid>
);
  1. Mount the tab on your service entity page
Copy
const serviceEntityPage = (
  <EntityLayout>
    {/* other tabs */}
    <EntityLayout.Route
      if={isGithubCodespacesAvailable}
      path="/github-codespaces"
      title="GitHub Codespaces"
    >
      {codespacesContent}
    </EntityLayout.Route>
  </EntityLayout>
);

Add a Codespaces menu page optional

  1. Wire a top level route in packages/app/src/App.tsx
Copy
import React from 'react';
import { Route } from 'react-router';
import { FlatRoutes } from '@backstage/core-app-api';
import { GithubCodespacesPage } from '@adityasinghal26/plugin-github-codespaces';

export const routes = (
  <FlatRoutes>
    {/* other routes */}
    <Route path="/github-codespaces" element={<GithubCodespacesPage />} />
  </FlatRoutes>
);
  1. Add a sidebar item in packages/app/src/components/Root/Root.tsx
Copy
import React, { PropsWithChildren } from 'react';
import { SidebarPage, Sidebar, SidebarItem, SidebarGroup } from '@backstage/core-components';
import { GitHubIcon } from '@backstage/core-components';

export const Root = ({ children }: PropsWithChildren<{}>) => (
  <SidebarPage>
    <Sidebar>
      {/* other sidebar items */}
      <SidebarGroup label="Menu">
        <SidebarItem icon={GitHubIcon} to="github-codespaces" text="Codespaces" />
      </SidebarGroup>
      {/* other sidebar items */}
    </Sidebar>
    {children}
  </SidebarPage>
);

Start the app

  1. Run the frontend
Copy
yarn start
  1. Run the backend
Copy
yarn start-backend
  1. Open the entity page tab at path github-codespaces under your entity. Or open the menu page at path github-codespaces

Backend setup

This plugin does not ship a backend plugin. It calls the GitHub API using the user session from the Backstage auth system. You only need GitHub auth configured in your backend.

Old backend system

  1. Add GitHub provider config to app-config.yaml
Copy
auth:
  environment: development
  providers:
    github:
      development:
        clientId: ${AUTH_GITHUB_CLIENT_ID}
        clientSecret: ${AUTH_GITHUB_CLIENT_SECRET}
        scopes:
          - repo
          - codespace
  1. Make sure the callback URL you set in GitHub matches http://localhost:7007/api/auth/github/handler/frame for local development

New backend system

  1. Install the GitHub auth provider module
Copy
yarn add --cwd packages/backend @backstage/plugin-auth-backend-module-github-provider
  1. Register the auth backend and the GitHub provider module in packages/backend/src/index.ts
Copy
import { createBackend } from '@backstage/backend-defaults';

const backend = createBackend();

// auth core plugin
backend.add(import('@backstage/plugin-auth-backend'));

// GitHub auth provider module
backend.add(import('@backstage/plugin-auth-backend-module-github-provider'));

backend.start();
  1. Add GitHub provider config to app-config.yaml
Copy
auth:
  environment: development
  providers:
    github:
      development:
        clientId: ${AUTH_GITHUB_CLIENT_ID}
        clientSecret: ${AUTH_GITHUB_CLIENT_SECRET}
        scopes:
          - repo
          - codespace

Notes on usage

  • The widget and the card create new codespaces with the entity name as the display name
  • After a codespace is created you can start it from the widget or the card
  • GitHub Enterprise is not supported yet

Changelog

This changelog is produced from commits made to the GitHub Codespaces 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.

Maintenance

  • Upgrade Backstage to 1.32 #8 merged 11 months ago

Breaking changes

  • None

Set up Backstage in minutes with Roadie