Merge pull request #5709 from TejasQ/tejask/2494

Scaffolder: Enable branch protection on new repo
This commit is contained in:
Fredrik Adelöw
2021-05-20 11:56:34 +02:00
committed by GitHub
4 changed files with 91 additions and 7 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-scaffolder-backend': patch
---
Add branch protection for default branches of scaffolded GitHub repositories
@@ -19,7 +19,10 @@ import {
ScmIntegrationRegistry,
} from '@backstage/integration';
import { Octokit } from '@octokit/rest';
import { initRepoAndPush } from '../../../stages/publish/helpers';
import {
enableBranchProtectionOnDefaultRepoBranch,
initRepoAndPush,
} from '../../../stages/publish/helpers';
import { getRepoSourceDirectory, parseRepoUrl } from './util';
import { createTemplateAction } from '../../createTemplateAction';
@@ -171,7 +174,7 @@ export function createPublishGithubAction(options: {
description: description,
});
const { data } = await repoCreationPromise;
const { data: newRepo } = await repoCreationPromise;
if (access?.startsWith(`${owner}/`)) {
const [, team] = access.split('/');
await client.teams.addOrUpdateRepoPermissionsInOrg({
@@ -212,8 +215,8 @@ export function createPublishGithubAction(options: {
}
}
const remoteUrl = data.clone_url;
const repoContentsUrl = `${data.html_url}/blob/master`;
const remoteUrl = newRepo.clone_url;
const repoContentsUrl = `${newRepo.html_url}/blob/master`;
await initRepoAndPush({
dir: getRepoSourceDirectory(ctx.workspacePath, ctx.input.sourcePath),
@@ -225,6 +228,18 @@ export function createPublishGithubAction(options: {
logger: ctx.logger,
});
try {
await enableBranchProtectionOnDefaultRepoBranch({
owner,
client,
repoName: newRepo.name,
});
} catch (e) {
throw new Error(
`Failed to add branch protection to '${newRepo.name}', ${e}`,
);
}
ctx.output('remoteUrl', remoteUrl);
ctx.output('repoContentsUrl', repoContentsUrl);
},
@@ -15,7 +15,10 @@
*/
import { PublisherBase, PublisherOptions, PublisherResult } from './types';
import { initRepoAndPush } from './helpers';
import {
enableBranchProtectionOnDefaultRepoBranch,
initRepoAndPush,
} from './helpers';
import {
GitHubIntegrationConfig,
GithubCredentialsProvider,
@@ -26,6 +29,7 @@ import path from 'path';
export type RepoVisibilityOptions = 'private' | 'internal' | 'public';
/** @deprecated use createPublishGithubAction instead */
export class GithubPublisher implements PublisherBase {
static async fromConfig(
config: GitHubIntegrationConfig,
@@ -99,6 +103,17 @@ export class GithubPublisher implements PublisherBase {
/\.git$/,
'/blob/master/catalog-info.yaml',
);
try {
await enableBranchProtectionOnDefaultRepoBranch({
owner,
client,
repoName: name,
});
} catch (e) {
throw new Error(`Failed to add branch protection to '${name}', ${e}`);
}
return { remoteUrl, catalogInfoUrl };
}
@@ -130,7 +145,7 @@ export class GithubPublisher implements PublisherBase {
description,
});
const { data } = await repoCreationPromise;
const { data: newRepo } = await repoCreationPromise;
try {
if (access?.startsWith(`${owner}/`)) {
@@ -156,6 +171,7 @@ export class GithubPublisher implements PublisherBase {
`Failed to add access to '${access}'. Status ${e.status} ${e.message}`,
);
}
return data?.clone_url;
return newRepo.clone_url;
}
}
@@ -17,6 +17,7 @@
import globby from 'globby';
import { Logger } from 'winston';
import { Git } from '@backstage/backend-common';
import { Octokit } from '@octokit/rest';
export async function initRepoAndPush({
dir,
@@ -67,3 +68,50 @@ export async function initRepoAndPush({
remote: 'origin',
});
}
type BranchProtectionOptions = {
client: Octokit;
owner: string;
repoName: string;
isRetry?: boolean;
};
export const enableBranchProtectionOnDefaultRepoBranch = async ({
repoName,
client,
owner,
}: BranchProtectionOptions): Promise<void> => {
const tryOnce = () => {
return client.repos.updateBranchProtection({
mediaType: {
/**
* 👇 we need this preview because allowing a custom
* reviewer count on branch protection is a preview
* feature
*
* More here: https://docs.github.com/en/rest/overview/api-previews#require-multiple-approving-reviews
*/
previews: ['luke-cage-preview'],
},
owner,
repo: repoName,
branch: 'master',
required_status_checks: { strict: true, contexts: [] },
restrictions: null,
enforce_admins: true,
required_pull_request_reviews: { required_approving_review_count: 1 },
});
};
try {
await tryOnce();
} catch (e) {
if (!e.message.includes('Branch not found')) {
throw e;
}
// GitHub has eventual consistency. Fail silently, wait, and try again.
await new Promise(resolve => setTimeout(resolve, 600));
await tryOnce();
}
};