/scaffolder-backend-module-azure-repositories

A collection of Backstage scaffolder backend modules for Azure repositories.

Primary LanguageTypeScriptApache License 2.0Apache-2.0

scaffolder-backend-module-azure-repositories

Welcome to the Microsoft Azure repository actions for the scaffolder-backend.

This plugin contains a collection of actions:

  • azure:repo:clone
  • azure:repo:push
  • azure:repo:pr

Getting started

Create your Backstage application using the Backstage CLI as described here: https://backstage.io/docs/getting-started/create-an-app.

Note: If you are using this plugin in a Backstage monorepo that contains the code for @backstage/plugin-scaffolder-backend, you need to modify your internal build processes to transpile files from the node_modules folder as well.

You need to configure the actions in your backend:

From your Backstage root directory

# From your Backstage root directory
yarn add --cwd packages/backend @antoniobergas/scaffolder-backend-module-azure-repositories

Configure the actions (you can check the docs to see all options):

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

import { CatalogClient } from '@backstage/catalog-client';
import { ScmIntegrations } from "@backstage/integration";

import {
  cloneAzureRepoAction,
  pushAzureRepoAction,
  pullRequestAzureRepoAction,
} from "@parfuemerie-douglas/scaffolder-backend-module-azure-repositories";

import { Router } from 'express';

import type { PluginEnvironment } from '../types';

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

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

const actions = [
  cloneAzureRepoAction({ integrations }),
  pushAzureRepoAction({ integrations, config: env.config }),
  pullRequestAzureRepoAction({ integrations }),
  ...createBuiltInActions({
    containerRunner,
    catalogClient,
    integrations,
    config: env.config,
    reader: env.reader,
  }),
];

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

The Azure repository actions use an Azure PAT (personal access token) for authorization. The PAT requires Read permission for Code for the azure:repo:clone action. For the azure:repo:push action the PAT requires Read & write permission for Code. Simply add the PAT to your app-config.yaml:

# app-config.yaml

integrations:
  azure:
    - host: dev.azure.com
      credentials:
        - personalAccessToken: ${AZURE_TOKEN}

Read more on integrations in Backstage in the Integrations documentation.

Using the template

After loading and configuring the Azure repository template actions, you can use the actions in your template:

# template.yaml

apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
  name: azure-repo-demo
  title: Azure Repository Test
  description: Clone and push to an Azure repository example.
spec:
  owner: parfuemerie-douglas
  type: service

  parameters:
    - title: Fill in some steps
      required:
        - name
        - owner
      properties:
        name:
          title: Project name
          type: string
          description: Choose a unique project name.
          ui:field: EntityNamePicker
          ui:autofocus: true
        owner:
          title: Owner
          type: string
          description: Select an owner for the Backstage component.
          ui:field: OwnerPicker
          ui:options:
            allowedKinds:
              - Group

  steps:
    - id: cloneAzureRepo
      name: Clone Azure Repo
      action: azure:repo:clone
      input:
        remoteUrl: "https://<MY_AZURE_ORGANIZATION>@dev.azure.com/<MY_AZURE_ORGANIZATION>/<MY_AZURE_PROJECT>/_git/<MY_AZURE_REPOSITORY>"
        branch: "main"
        targetPath: ./sub-directory

    - id: fetch
      name: Template Skeleton
      action: fetch:template
      input:
        url: ./skeleton
        targetPath: ./sub-directory
        values:
          name: ${{ parameters.name }}
          owner: ${{ parameters.owner }}

    - id: pushAzureRepo
      name: Push to Remote Azure Repo
      action: azure:repo:push
      input:
        branch: <MY_AZURE_REPOSITORY_BRANCH>
        sourcePath: ./sub-directory
        gitCommitMessage: Add ${{ parameters.name }} project files

    - id: pullRequestAzureRepo
      name: Create a Pull Request to Azure Repo
      action: azure:repo:pr
      input:
        sourceBranch: <MY_AZURE_REPOSITORY_BRANCH>
        targetBranch: "main"
        repoId: <MY_AZURE_REPOSITORY>
        title: ${{ parameters.name }}
        project: <MY_AZURE_PROJECT>
        supportsIterations: false

    - id: register
      name: Register
      action: catalog:register
      input:
        repoContentsUrl: "dev.azure.com?owner=<MY_AZURE_PROJECT>&repo=<MY_AZURE_REPOSITORY>&organization=<MY_AZURE_ORGANIZATION>&version=<MY_AZURE_REPOSITORY_BRANCH>"
        catalogInfoPath: "/catalog-info.yaml"

  output:
    links:
      - title: Repository
        url: "dev.azure.com?owner=<MY_AZURE_PROJECT>&repo=<MY_AZURE_REPOSITORY>&organization=<MY_AZURE_ORGANIZATION>"
      - title: Open in catalog
        icon: catalog
        entityRef: ${{ steps.register.output.entityRef }}

Replace <MY_AZURE_ORGANIZATION> with the name of your Azure DevOps organization, <MY_AZURE_PROJECT> with the name of your Azure DevOps project, <MY_AZURE_REPOSITORY_BRANCH with the name of the desired Azure DevOps repository branch, and <MY_AZURE_REPOSITORY> with the name of your Azure DevOps repository.

NOTE: You will not be able to register the Pull Request since the file will not exist from the main branch!

You can find a list of all registred actions including their parameters at the /create/actions route in your Backstage application.