Scaffolder Git Actions logo

Backstage Scaffolder Git Actions Plugin

Created by Drew Hill

Scaffolder Git Actions is a plugin for Backstage that adds git actions to the scaffolder backend. It lets your templates run git commands during scaffolding. It includes two actions named git and git clone. With these you can script common git tasks inside a template run.

At a high level, the generic git action runs a command such as commit or push or tag within a chosen working directory in the workspace. The clone action clones a repository into the workspace so later steps can work with it. You pass arguments as needed. This keeps templates simple while still giving you control.

Typical use cases are straightforward. Bootstrap a new repo from a template then add an initial commit. Clone a utilities repo to copy files or read version info before you generate code. Create a tag after you scaffold a service. Support monorepos by cloning a target and committing changes back. Handle small migrations that benefit from real git history.

The plugin works with your existing Backstage source control integrations such as GitHub or GitLab or Azure DevOps. It requires git in the runtime environment. It does not replace publish steps from other modules. It complements them. If you want fine control over git inside templates, this plugin keeps that logic close to your scaffolder steps.

Installation Instructions

These instructions apply to self-hosted Backstage only.

Install the package

Your backend host must have Git installed.

Run this in the root of your Backstage repo

Copy
yarn add --cwd packages/backend @mdude2314/backstage-plugin-scaffolder-git-actions

Wire it into the legacy backend

Add the actions to your scaffolder backend router

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

import { gitCloneAction, gitAction } from '@mdude2314/backstage-plugin-scaffolder-git-actions';
import { ScmIntegrations } from '@backstage/integration';
import { createBuiltinActions, createRouter } from '@backstage/plugin-scaffolder-backend';

export default async function createPlugin(
  env: PluginEnvironment,
): Promise<express.Router> {
  const { catalogClient } = env;

  const integrations = ScmIntegrations.fromConfig(env.config);

  const builtInActions = createBuiltinActions({
    catalogClient,
    integrations,
    config: env.config,
    reader: env.reader,
  });

  const actions = [
    gitAction(),
    gitCloneAction(),
    ...builtInActions,
  ];

  return await createRouter({
    logger: env.logger,
    config: env.config,
    database: env.database,
    reader: env.reader,
    catalogClient,
    actions,
  });
}

Restart your backend after you save the file.

Wire it into the new backend system

Create a small backend module that registers the actions

Copy
// packages/backend/src/modules/scaffolder-git-actions.ts

import { createBackendModule } from '@backstage/backend-plugin-api';
import { scaffolderActionsExtensionPoint } from '@backstage/plugin-scaffolder-node';
import { gitAction, gitCloneAction } from '@mdude2314/backstage-plugin-scaffolder-git-actions';

export const scaffolderGitActionsModule = createBackendModule({
  pluginId: 'scaffolder',
  moduleId: 'git-actions',
  register(env) {
    env.registerInit({
      deps: { actions: scaffolderActionsExtensionPoint },
      async init({ actions }) {
        actions.addActions(
          gitAction(),
          gitCloneAction(),
        );
      },
    });
  },
});

Register the module in your backend entry

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

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

const backend = createBackend();

// Ensure the scaffolder backend plugin is added
backend.add(import('@backstage/plugin-scaffolder-backend'));

// Add the module that registers the git actions
backend.add(import('./modules/scaffolder-git-actions'));

backend.start();

Restart your backend after you save the files.

Add a template that uses the generic git action

Place this template YAML where your catalog reads templates. For example a folder that your app-config loads as a catalog location. This makes the action show up when running a scaffolder task

Copy
---
apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
  name: git-generic-demo
  title: Run a git command in the workspace
  description: Run an arbitrary git subcommand in the scaffolder workspace
spec:
  owner: team
  type: service

  parameters:
    - title: Generic git
      properties:
        command:
          title: Command
          type: string
          description: Git subcommand to run such as commit
        workingDirectory:
          title: Working Directory
          type: string
          description: Directory within the scaffolder workspace to run the command
        args:
          title: Args
          type: array
          description: Extra arguments passed to the git command

  steps:
    - id: git
      name: git
      action: git
      input:
        command: ${{ parameters.command }}
        workingDirectory: ${{ parameters.workingDirectory }}
        args: ${{ parameters.args }}

Add a template that uses the clone action

Copy
---
apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
  name: git-clone-demo
  title: Clone a repository into the workspace
  description: Clone using the git clone action
spec:
  owner: team
  type: service

  parameters:
    - title: Clone
      properties:
        repoUrl:
          title: URL
          type: string
          description: URL to clone
        args:
          title: Args
          type: array
          description: Extra arguments passed to git clone

  steps:
    - id: clone
      name: Clone
      action: git:clone
      input:
        repoUrl: ${{ parameters.repoUrl }}
        args: ${{ parameters.args }}

Run your app

Start your Backstage app as you normally do. Open the Create page and use a template that calls the git or git clone actions.

Changelog

The Scaffolder Git Actions plugin has not seen any significant changes since 6 months ago.

Set up Backstage in minutes with Roadie