Merge pull request #27796 from stegosaurus21/stegosaurus21/fix-create-github-env-auth

Make GitHub environment Scaffolder action use auth to resolve reviewers
This commit is contained in:
Ben Lambert
2024-12-13 16:57:38 +01:00
committed by GitHub
5 changed files with 46 additions and 6 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-scaffolder-backend-module-github': patch
---
Change `github:environment:create` action to request and use a token when resolving reviewer entity refs from the Backstage catalog.
@@ -3,6 +3,7 @@
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
```ts
import { AuthService } from '@backstage/backend-plugin-api';
import { BackendFeature } from '@backstage/backend-plugin-api';
import { CatalogApi } from '@backstage/catalog-client';
import { Config } from '@backstage/config';
@@ -103,6 +104,7 @@ export function createGithubDeployKeyAction(options: {
export function createGithubEnvironmentAction(options: {
integrations: ScmIntegrationRegistry;
catalogClient?: CatalogApi;
auth?: AuthService;
}): TemplateAction<
{
repoUrl: string;
@@ -20,6 +20,7 @@ import { TemplateAction } from '@backstage/plugin-scaffolder-node';
import { ConfigReader } from '@backstage/config';
import { ScmIntegrations } from '@backstage/integration';
import { CatalogApi } from '@backstage/catalog-client';
import { mockCredentials, mockServices } from '@backstage/backend-test-utils';
const mockOctokit = {
rest: {
@@ -71,6 +72,14 @@ describe('github:environment:create', () => {
});
const integrations = ScmIntegrations.fromConfig(config);
const credentials = mockCredentials.user();
const token = mockCredentials.service.token({
onBehalfOf: credentials,
targetPluginId: 'catalog',
});
let action: TemplateAction<any>;
const mockContext = createMockActionContext({
@@ -78,6 +87,7 @@ describe('github:environment:create', () => {
repoUrl: 'github.com?repo=repository&owner=owner',
name: 'envname',
},
secrets: { backstageToken: token },
});
beforeEach(() => {
@@ -122,6 +132,7 @@ describe('github:environment:create', () => {
action = createGithubEnvironmentAction({
integrations,
catalogClient: mockCatalogClient as CatalogApi,
auth: mockServices.auth(),
});
});
@@ -453,6 +464,13 @@ describe('github:environment:create', () => {
},
});
expect(mockCatalogClient.getEntitiesByRefs).toHaveBeenCalledWith(
{
entityRefs: ['group:default/team-a', 'user:default/johndoe'],
},
{ token },
);
expect(
mockOctokit.rest.repos.createOrUpdateEnvironment,
).toHaveBeenCalledWith({
@@ -26,6 +26,7 @@ import Sodium from 'libsodium-wrappers';
import { examples } from './gitHubEnvironment.examples';
import { CatalogApi } from '@backstage/catalog-client';
import { Entity } from '@backstage/catalog-model';
import { AuthService } from '@backstage/backend-plugin-api';
/**
* Creates an `github:environment:create` Scaffolder action that creates a Github Environment.
@@ -35,8 +36,9 @@ import { Entity } from '@backstage/catalog-model';
export function createGithubEnvironmentAction(options: {
integrations: ScmIntegrationRegistry;
catalogClient?: CatalogApi;
auth?: AuthService;
}) {
const { integrations, catalogClient } = options;
const { integrations, catalogClient, auth } = options;
// For more information on how to define custom actions, see
// https://backstage.io/docs/features/software-templates/writing-custom-actions
return createTemplateAction<{
@@ -140,7 +142,8 @@ export function createGithubEnvironmentAction(options: {
reviewers: {
title: 'Reviewers',
type: 'array',
description: 'Reviewers for this environment',
description:
'Reviewers for this environment. Must be a list of Backstage entity references.',
items: {
type: 'string',
},
@@ -163,6 +166,11 @@ export function createGithubEnvironmentAction(options: {
reviewers,
} = ctx.input;
const { token } = (await auth?.getPluginRequestToken({
onBehalfOf: await ctx.getInitiatorCredentials(),
targetPluginId: 'catalog',
})) ?? { token: ctx.secrets?.backstageToken };
// When environment creation step is executed right after a repo publish step, the repository might not be available immediately.
// Add a 2-second delay before initiating the steps in this action.
await new Promise(resolve => setTimeout(resolve, 2000));
@@ -190,9 +198,14 @@ export function createGithubEnvironmentAction(options: {
if (reviewers) {
let reviewersEntityRefs: Array<Entity | undefined> = [];
// Fetch reviewers from Catalog
const catalogResponse = await catalogClient?.getEntitiesByRefs({
entityRefs: reviewers,
});
const catalogResponse = await catalogClient?.getEntitiesByRefs(
{
entityRefs: reviewers,
},
{
token,
},
);
if (catalogResponse?.items?.length) {
reviewersEntityRefs = catalogResponse.items;
}
@@ -51,8 +51,9 @@ export const githubModule = createBackendModule({
scaffolder: scaffolderActionsExtensionPoint,
config: coreServices.rootConfig,
discovery: coreServices.discovery,
auth: coreServices.auth,
},
async init({ scaffolder, config, discovery }) {
async init({ scaffolder, config, discovery, auth }) {
const integrations = ScmIntegrations.fromConfig(config);
const githubCredentialsProvider =
DefaultGithubCredentialsProvider.fromIntegrations(integrations);
@@ -75,6 +76,7 @@ export const githubModule = createBackendModule({
createGithubEnvironmentAction({
integrations,
catalogClient,
auth,
}),
createGithubIssuesLabelAction({
integrations,