Scaffolder: Enable branch protection on new repo

Signed-off-by: Tejas Kumar <tejask@spotify.com>
This commit is contained in:
Tejas Kumar
2021-05-18 11:41:31 +02:00
parent dc631231b3
commit c41964f89b
2 changed files with 81 additions and 3 deletions
@@ -15,7 +15,10 @@
*/
import { PublisherBase, PublisherOptions, PublisherResult } from './types';
import { initRepoAndPush } from './helpers';
import {
enableBranchProtectionOnDefaultRepoBranch,
initRepoAndPush,
} from './helpers';
import {
GitHubIntegrationConfig,
GithubCredentialsProvider,
@@ -99,6 +102,19 @@ 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.message}`,
);
}
return { remoteUrl, catalogInfoUrl };
}
@@ -130,7 +146,7 @@ export class GithubPublisher implements PublisherBase {
description,
});
const { data } = await repoCreationPromise;
const { data: newRepo } = await repoCreationPromise;
try {
if (access?.startsWith(`${owner}/`)) {
@@ -156,6 +172,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, RestEndpointMethodTypes } from '@octokit/rest';
export async function initRepoAndPush({
dir,
@@ -67,3 +68,63 @@ export async function initRepoAndPush({
remote: 'origin',
});
}
type BranchProtectionOptions = {
client: Octokit;
owner: string;
repoName: string;
isRetry?: boolean;
};
export const enableBranchProtectionOnDefaultRepoBranch = async ({
repoName,
client,
owner,
isRetry = false,
}: BranchProtectionOptions): Promise<
RestEndpointMethodTypes['repos']['updateBranchProtection']['response']
> => {
const { data: repo } = await client.repos.get({
owner,
repo: repoName,
});
try {
const response = await client.repos.updateBranchProtection({
headers: {
Accept:
/**
* 👇 we need this header 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
*/
'application/vnd.github.luke-cage-preview+json',
},
owner,
repo: repoName,
branch: repo.default_branch,
required_status_checks: { strict: true, contexts: [] },
restrictions: null,
enforce_admins: true,
required_pull_request_reviews: { required_approving_review_count: 1 },
});
return response;
} catch (e) {
if (!isRetry && e.message.includes('Branch not found')) {
// GitHub has eventual consistency. Fail silently, wait, and try again.
await new Promise(resolve => setTimeout(resolve, 600));
return await enableBranchProtectionOnDefaultRepoBranch({
repoName,
client,
owner,
isRetry: true,
});
}
throw e;
}
};