Skip to content
This repository was archived by the owner on Jan 21, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions src/bot/events/handlers/cleanHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,17 @@ export async function cleanHandler(this: EventHandler): Promise<void> {
throw new EventHandlerError();
}

const { comment } = payload;
const { comment, sender } = payload;

const reactionParams = { owner: pr.owner, repo: pr.repo, comment_id: comment.id };
const reactionId = await reactToComment(ctx, octokit, { ...reactionParams, content: "eyes" });
await cleanComments(ctx, octokit, { ...commentParams });
await cleanComments(ctx, octokit, comment, parsedCommand.all, { ...commentParams, requester: sender.login });
await Promise.all([
reactionId ? await removeReactionToComment(ctx, octokit, { ...reactionParams, reaction_id: reactionId }) : null,
reactionId
? await removeReactionToComment(ctx, octokit, { ...reactionParams, reaction_id: reactionId }).catch((e) => {
ctx.logger.error(e, "Failed to remove reaction");
})
: null,
await reactToComment(ctx, octokit, { ...reactionParams, content: "+1" }),
]);
}
2 changes: 1 addition & 1 deletion src/bot/parse/ParsedCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export class CancelCommand extends ParsedCommand {
}

export class CleanCommand extends ParsedCommand {
constructor() {
constructor(public all: boolean = false) {
super("clean");
}
}
Expand Down
23 changes: 19 additions & 4 deletions src/command-configs/help/parts/commands_preset.pug
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
div(class="preset " + preset.repos.join(' '))
div(class="preset " + (typeof(preset.repos) !== 'undefined' ? preset.repos : []).join(' '))
h6.mb-md(id="link-"+ commandName + "-" + presetId) #{commandStart} #{ commandName } #{presetId === 'default' ? '' : presetId}
p.mb-md.muted
| Works in these repos:&nbsp;
each repo in preset.repos
span.ms-label #{repo}
if typeof(preset.repos) !== 'undefined'
| Works in these repos:&nbsp;
each repo in (typeof(preset.repos) !== 'undefined' ? preset.repos : [])
span.ms-label #{repo}
else
| Works in all repos
-let defaultArgs = []
if preset.args && Object.values(preset.args).length > 0
div.preset-args.mb-lg.ml-md
Expand All @@ -15,17 +18,29 @@ div(class="preset " + preset.repos.join(' '))
| --#{arg.label}
div.col-8.lowercase
each one, i in arg.type_one_of
if one.explanation
p(style={"margin-top": 0}) #{one.explanation}&nbsp;
span.mb-sm
if i === 0
| #{one} (default)&nbsp;
else
| | #{one}&nbsp;
if arg.type_boolean
div.col-4.lowercase
| --#{arg.label}
div.col-8
if arg.explanation
p(style={"margin-top": 0}) #{arg.explanation}&nbsp;
span.mb-sm
| Default: #{arg.default}&nbsp;
else if arg.type_rule
div.col-4.lowercase
| --#{arg.label}
span(style="color: red;") &nbsp;*&nbsp;
| (required):
div.col-8.lowercase
if arg.explanation
p(style={"margin-top": 0}) #{arg.explanation}&nbsp;
| #{arg.type_rule}&nbsp;
if arg.example
| (Example: "#{arg.example}")
Expand Down
2 changes: 1 addition & 1 deletion src/command-configs/help/parts/navigation.pug
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ div.sticky-nav
if cfg.command.presets
ul.nav-preset
each preset, presetId in cfg.command.presets
li(class="preset-link " + preset.repos.join(' ') + (presetId === 'default' ? ' hidden' : ''))
li(class="preset-link " + (typeof(preset.repos) !== 'undefined' ? preset.repos : []).join(' ') + (presetId === 'default' ? ' hidden' : ''))
a(href="\#link-" + commandName + "-" + presetId) #{ presetId }
| Env Variables
ul
Expand Down
18 changes: 15 additions & 3 deletions src/command-configs/renderHelpPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,19 @@ function prepareConfigs(cmdConfigs: CommandConfigs): CommandConfigs {

// these commands are added here, as they are defined inside of bot
newCmdConfigs.help = mockStaticConfig("Generates the help page & provides a link.");
newCmdConfigs.clean = mockStaticConfig("Clears bot comments in the PR.");
newCmdConfigs.clean = mockStaticConfig("Clears bot comments in the PR.", {
default: {
description: "Clears all bot comments in the PR. ",
args: {
all: {
label: "all",
type_boolean: true,
default: false,
explanation: "Clears all bot comments in the PR, including human comments requesting a command-bot.",
},
},
},
});

// clean up excluded
for (const cmdName in cmdConfigs) {
Expand All @@ -55,7 +67,7 @@ function prepareConfigs(cmdConfigs: CommandConfigs): CommandConfigs {
}

// append local (or "hardcoded") commands into documentation
function mockStaticConfig(description: string) {
const config: CmdJson = { command: { description, configuration: {} } };
function mockStaticConfig(description: string, presets?: CmdJson["command"]["presets"]): CmdJson {
const config: CmdJson = { command: { description, configuration: {}, presets } };
return config;
}
5 changes: 3 additions & 2 deletions src/commander/commander.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,9 @@ export function getCommanderFromConfiguration(
.command("clear")
.alias("clean")
.exitOverride()
.action(() => {
parsedCommand = new CleanCommand();
.option("--all", "clear all comments, including bot and requesters' comments")
.action((options: { all: boolean }) => {
parsedCommand = new CleanCommand(options.all);
});

root
Expand Down
22 changes: 19 additions & 3 deletions src/github.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ import { Logger } from "@eng-automation/js";
import { OctokitResponse } from "@octokit/plugin-paginate-rest/dist-types/types";
import { RequestError } from "@octokit/request-error";
import { EndpointInterface, Endpoints, RequestInterface } from "@octokit/types";
import { IssueComment } from "@octokit/webhooks-types";
import { Mutex } from "async-mutex";
import { Probot } from "probot";

import { config } from "src/config";
import { PullRequestTask } from "src/task";
import { CommandOutput, Context } from "src/types";
import { displayError, Err, millisecondsDelay, Ok } from "src/utils";
Expand Down Expand Up @@ -251,6 +253,8 @@ export const removeReactionToComment = async (
export const cleanComments = async (
ctx: Context,
octokit: Octokit,
originalComment: IssueComment,
isAll: boolean,
...args: Parameters<typeof octokit.issues.listComments>
): Promise<void> => {
if (ctx.disablePRComment) {
Expand Down Expand Up @@ -281,10 +285,22 @@ export const cleanComments = async (
params.page = params.page + 1;
ctx.logger.debug(null, `cleanComments: increase page ${params.page}`);
}
// save ids
botCommentIds.push(...response.data.filter((comment) => comment.user?.type === "Bot").map((r) => r.id));
const filteredComments = response.data
.filter((comment) => {
const isBot = comment.user?.type === "Bot";
// to avoid deleting the original comment
const isOriginalComment = comment.id === originalComment.id;
// testing each comment with real commander and pulling repos (even cached) is quite expensive
// so we just check if comment has the command pattern, assuming that if it includes pattern, it's a request to bot
const commandPattern = new RegExp(`^${config.botPullRequestCommentMention} .*$`, "i");

Check failure

Code scanning / CodeQL

Regular expression injection

This regular expression is constructed from a [environment variable](1).
const hasCommand = comment.body?.split("\n").find((line) => commandPattern.test(line));
return (isBot || (isAll && hasCommand)) && !isOriginalComment;
})
.map((comment) => comment.id);

botCommentIds.push(...filteredComments);
} else {
ctx.logger.error(response, "cleanComments: listComments ended up unsuccessfully");
ctx.logger.error(response, "cleanComments: listComments ended up with error");
stopped = true;
}
}
Expand Down
12 changes: 12 additions & 0 deletions src/schema/schema.cmd.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@
"label": {
"type": "string"
},
"explanation": {
"type": "string"
},
"type_one_of": {
"type": "array",
"items": {
Expand All @@ -104,8 +107,14 @@
"type_rule": {
"type": "string"
},
"type_boolean": {
"type": "boolean"
},
"example": {
"type": "string"
},
"default": {
"type": "string"
}
},
"anyOf": [
Expand All @@ -120,6 +129,9 @@
},
{
"required": ["label", "type_rule", "example"]
},
{
"required": ["label", "type_boolean", "explanation", "default"]
}
]
}
Expand Down