Add features for "publish:github" action

Implement "Required approving review count", "Restrictions", and "Required commit signing" support for "publish:github" action.

Signed-off-by: Trevor Grieger <tgrieger@salesforce.com>
This commit is contained in:
Trevor Grieger
2023-01-11 00:29:48 -05:00
parent 51ba911550
commit a6808b67a7
8 changed files with 153 additions and 2 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-scaffolder-backend': patch
---
Implement "Required approving review count", "Restrictions", and "Required commit signing" support for "publish:github" action
+27
View File
@@ -211,6 +211,14 @@ export function createGithubRepoCreateAction(options: {
apps?: string[] | undefined;
}
| undefined;
requiredApprovingReviewCount?: number | undefined;
restrictions?:
| {
users: string[] | undefined;
teams: string[] | undefined;
apps?: string[] | undefined;
}
| undefined;
requiredStatusCheckContexts?: string[] | undefined;
requireBranchesToBeUpToDate?: boolean | undefined;
requiredConversationResolution?: boolean | undefined;
@@ -236,6 +244,7 @@ export function createGithubRepoCreateAction(options: {
hasIssues?: boolean | undefined;
token?: string | undefined;
topics?: string[] | undefined;
requireCommitSigning?: boolean | undefined;
}>;
// @public
@@ -261,11 +270,20 @@ export function createGithubRepoPushAction(options: {
apps?: string[];
}
| undefined;
requiredApprovingReviewCount?: number | undefined;
restrictions?:
| {
users: string[] | undefined;
teams: string[] | undefined;
apps?: string[] | undefined;
}
| undefined;
requiredStatusCheckContexts?: string[] | undefined;
requireBranchesToBeUpToDate?: boolean | undefined;
requiredConversationResolution?: boolean | undefined;
sourcePath?: string | undefined;
token?: string | undefined;
requireCommitSigning?: boolean | undefined;
}>;
// @public
@@ -405,6 +423,14 @@ export function createPublishGithubAction(options: {
apps?: string[];
}
| undefined;
requiredApprovingReviewCount?: number | undefined;
restrictions?:
| {
users: string[] | undefined;
teams: string[] | undefined;
apps?: string[] | undefined;
}
| undefined;
requireCodeOwnerReviews?: boolean | undefined;
dismissStaleReviews?: boolean | undefined;
requiredStatusCheckContexts?: string[] | undefined;
@@ -432,6 +458,7 @@ export function createPublishGithubAction(options: {
hasIssues?: boolean | undefined;
token?: string | undefined;
topics?: string[] | undefined;
requireCommitSigning?: boolean | undefined;
}>;
// @public
@@ -59,6 +59,12 @@ export function createGithubRepoCreateAction(options: {
teams?: string[];
apps?: string[];
};
requiredApprovingReviewCount?: number;
restrictions?: {
users: string[];
teams: string[];
apps?: string[];
};
requiredStatusCheckContexts?: string[];
requireBranchesToBeUpToDate?: boolean;
requiredConversationResolution?: boolean;
@@ -83,6 +89,7 @@ export function createGithubRepoCreateAction(options: {
hasIssues?: boolean;
token?: string;
topics?: string[];
requireCommitSigning?: boolean;
}>({
id: 'github:repo:create',
description: 'Creates a GitHub repository.',
@@ -97,6 +104,8 @@ export function createGithubRepoCreateAction(options: {
access: inputProps.access,
requireCodeOwnerReviews: inputProps.requireCodeOwnerReviews,
bypassPullRequestAllowances: inputProps.bypassPullRequestAllowances,
requiredApprovingReviewCount: inputProps.requiredApprovingReviewCount,
restrictions: inputProps.restrictions,
requiredStatusCheckContexts: inputProps.requiredStatusCheckContexts,
requireBranchesToBeUpToDate: inputProps.requireBranchesToBeUpToDate,
requiredConversationResolution:
@@ -115,6 +124,7 @@ export function createGithubRepoCreateAction(options: {
hasIssues: inputProps.hasIssues,
token: inputProps.token,
topics: inputProps.topics,
requiredCommitSigning: inputProps.requiredCommitSigning,
},
},
output: {
@@ -57,11 +57,20 @@ export function createGithubRepoPushAction(options: {
apps?: string[];
}
| undefined;
requiredApprovingReviewCount?: number;
restrictions?:
| {
users: string[];
teams: string[];
apps?: string[];
}
| undefined;
requiredStatusCheckContexts?: string[];
requireBranchesToBeUpToDate?: boolean;
requiredConversationResolution?: boolean;
sourcePath?: string;
token?: string;
requiredCommitSigning?: boolean;
}>({
id: 'github:repo:push',
description:
@@ -76,6 +85,8 @@ export function createGithubRepoPushAction(options: {
dismissStaleReviews: inputProps.dismissStaleReviews,
requiredStatusCheckContexts: inputProps.requiredStatusCheckContexts,
bypassPullRequestAllowances: inputProps.bypassPullRequestAllowances,
requiredApprovingReviewCount: inputProps.requiredApprovingReviewCount,
restrictions: inputProps.restrictions,
requireBranchesToBeUpToDate: inputProps.requireBranchesToBeUpToDate,
requiredConversationResolution:
inputProps.requiredConversationResolution,
@@ -87,6 +98,7 @@ export function createGithubRepoPushAction(options: {
gitAuthorEmail: inputProps.gitAuthorEmail,
sourcePath: inputProps.sourcePath,
token: inputProps.token,
requiredCommitSigning: inputProps.requiredCommitSigning,
},
},
output: {
@@ -109,10 +121,13 @@ export function createGithubRepoPushAction(options: {
requireCodeOwnerReviews = false,
dismissStaleReviews = false,
bypassPullRequestAllowances,
requiredApprovingReviewCount = 1,
restrictions,
requiredStatusCheckContexts = [],
requireBranchesToBeUpToDate = true,
requiredConversationResolution = false,
token: providedToken,
requiredCommitSigning = false,
} = ctx.input;
const { owner, repo } = parseRepoUrl(repoUrl, integrations);
@@ -148,6 +163,8 @@ export function createGithubRepoPushAction(options: {
repo,
requireCodeOwnerReviews,
bypassPullRequestAllowances,
requiredApprovingReviewCount,
restrictions,
requiredStatusCheckContexts,
requireBranchesToBeUpToDate,
requiredConversationResolution,
@@ -157,6 +174,7 @@ export function createGithubRepoPushAction(options: {
gitAuthorName,
gitAuthorEmail,
dismissStaleReviews,
requiredCommitSigning,
);
ctx.output('remoteUrl', remoteUrl);
@@ -271,6 +271,14 @@ export async function initRepoPushAndProtect(
apps?: string[];
}
| undefined,
requiredApprovingReviewCount: number,
restrictions:
| {
users: string[];
teams: string[];
apps?: string[];
}
| undefined,
requiredStatusCheckContexts: string[],
requireBranchesToBeUpToDate: boolean,
requiredConversationResolution: boolean,
@@ -280,6 +288,7 @@ export async function initRepoPushAndProtect(
gitAuthorName?: string,
gitAuthorEmail?: string,
dismissStaleReviews?: boolean,
requiredCommitSigning?: boolean,
) {
const gitAuthorInfo = {
name: gitAuthorName
@@ -316,12 +325,15 @@ export async function initRepoPushAndProtect(
logger,
defaultBranch,
bypassPullRequestAllowances,
requiredApprovingReviewCount,
restrictions,
requireCodeOwnerReviews,
requiredStatusCheckContexts,
requireBranchesToBeUpToDate,
requiredConversationResolution,
enforceAdmins: protectEnforceAdmins,
dismissStaleReviews: dismissStaleReviews,
requiredCommitSigning: requiredCommitSigning,
});
} catch (e) {
assertError(e);
@@ -225,6 +225,46 @@ const sourcePath = {
type: 'string',
};
const requiredApprovingReviewCount = {
title: 'Required approving review count',
type: 'number',
description: `Specify the number of reviewers required to approve pull requests. Use a number between 1 and 6 or 0 to not require reviewers. Defaults to 1.`,
};
const restrictions = {
title: 'Restrict who can push to the protected branch',
description:
'Restrict who can push to the protected branch. User, app, and team restrictions are only available for organization-owned repositories.',
type: 'object',
additionalProperties: false,
properties: {
apps: {
type: 'array',
items: {
type: 'string',
},
},
users: {
type: 'array',
items: {
type: 'string',
},
},
teams: {
type: 'array',
items: {
type: 'string',
},
},
},
};
const requiredCommitSigning = {
title: 'Require commit signing',
type: 'boolean',
description: `Require commit signing so that you must sign commits on this branch.`,
};
export { access };
export { allowMergeCommit };
export { allowRebaseMerge };
@@ -243,6 +283,8 @@ export { homepage };
export { protectDefaultBranch };
export { protectEnforceAdmins };
export { bypassPullRequestAllowances };
export { requiredApprovingReviewCount };
export { restrictions };
export { repoUrl };
export { repoVisibility };
export { requireCodeOwnerReviews };
@@ -256,3 +298,4 @@ export { hasWiki };
export { sourcePath };
export { token };
export { topics };
export { requiredCommitSigning };
@@ -190,11 +190,18 @@ type BranchProtectionOptions = {
teams?: string[];
apps?: string[];
};
requiredApprovingReviewCount?: number;
restrictions?: {
users: string[];
teams: string[];
apps?: string[];
};
requireBranchesToBeUpToDate?: boolean;
requiredConversationResolution?: boolean;
defaultBranch?: string;
enforceAdmins?: boolean;
dismissStaleReviews?: boolean;
requiredCommitSigning?: boolean;
};
export const enableBranchProtectionOnDefaultRepoBranch = async ({
@@ -204,12 +211,15 @@ export const enableBranchProtectionOnDefaultRepoBranch = async ({
logger,
requireCodeOwnerReviews,
bypassPullRequestAllowances,
requiredApprovingReviewCount,
restrictions,
requiredStatusCheckContexts = [],
requireBranchesToBeUpToDate = true,
requiredConversationResolution = false,
defaultBranch = 'master',
enforceAdmins = true,
dismissStaleReviews = false,
requiredCommitSigning = false,
}: BranchProtectionOptions): Promise<void> => {
const tryOnce = async () => {
try {
@@ -231,16 +241,24 @@ export const enableBranchProtectionOnDefaultRepoBranch = async ({
strict: requireBranchesToBeUpToDate,
contexts: requiredStatusCheckContexts,
},
restrictions: null,
restrictions: restrictions ?? null,
enforce_admins: enforceAdmins,
required_pull_request_reviews: {
required_approving_review_count: 1,
required_approving_review_count: requiredApprovingReviewCount,
require_code_owner_reviews: requireCodeOwnerReviews,
bypass_pull_request_allowances: bypassPullRequestAllowances,
dismiss_stale_reviews: dismissStaleReviews,
},
required_conversation_resolution: requiredConversationResolution,
});
if (requiredCommitSigning) {
await client.rest.repos.createCommitSignatureProtection({
owner,
repo: repoName,
branch: defaultBranch,
});
}
} catch (e) {
assertError(e);
if (
@@ -69,6 +69,14 @@ export function createPublishGithubAction(options: {
apps?: string[];
}
| undefined;
requiredApprovingReviewCount?: number;
restrictions?:
| {
users: string[];
teams: string[];
apps?: string[];
}
| undefined;
requireCodeOwnerReviews?: boolean;
dismissStaleReviews?: boolean;
requiredStatusCheckContexts?: string[];
@@ -95,6 +103,7 @@ export function createPublishGithubAction(options: {
hasIssues?: boolean | undefined;
token?: string;
topics?: string[];
requiredCommitSigning?: boolean;
}>({
id: 'publish:github',
description:
@@ -109,6 +118,8 @@ export function createPublishGithubAction(options: {
homepage: inputProps.homepage,
access: inputProps.access,
bypassPullRequestAllowances: inputProps.bypassPullRequestAllowances,
requiredApprovingReviewCount: inputProps.requiredApprovingReviewCount,
restrictions: inputProps.restrictions,
requireCodeOwnerReviews: inputProps.requireCodeOwnerReviews,
dismissStaleReviews: inputProps.dismissStaleReviews,
requiredStatusCheckContexts: inputProps.requiredStatusCheckContexts,
@@ -136,6 +147,7 @@ export function createPublishGithubAction(options: {
hasIssues: inputProps.hasIssues,
token: inputProps.token,
topics: inputProps.topics,
requiredCommitSigning: inputProps.requiredCommitSigning,
},
},
output: {
@@ -155,6 +167,8 @@ export function createPublishGithubAction(options: {
requireCodeOwnerReviews = false,
dismissStaleReviews = false,
bypassPullRequestAllowances,
requiredApprovingReviewCount = 1,
restrictions,
requiredStatusCheckContexts = [],
requireBranchesToBeUpToDate = true,
requiredConversationResolution = false,
@@ -178,6 +192,7 @@ export function createPublishGithubAction(options: {
hasIssues = undefined,
topics,
token: providedToken,
requiredCommitSigning = false,
} = ctx.input;
const octokitOptions = await getOctokitOptions({
@@ -233,6 +248,8 @@ export function createPublishGithubAction(options: {
repo,
requireCodeOwnerReviews,
bypassPullRequestAllowances,
requiredApprovingReviewCount,
restrictions,
requiredStatusCheckContexts,
requireBranchesToBeUpToDate,
requiredConversationResolution,
@@ -242,6 +259,7 @@ export function createPublishGithubAction(options: {
gitAuthorName,
gitAuthorEmail,
dismissStaleReviews,
requiredCommitSigning,
);
ctx.output('remoteUrl', remoteUrl);