Skip to content

Commit

Permalink
Allow commands in review submissions (#149)
Browse files Browse the repository at this point in the history
  • Loading branch information
timja authored Nov 6, 2022
1 parent 0fbd6a7 commit b74c409
Show file tree
Hide file tree
Showing 12 changed files with 187 additions and 21 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ Run `smee --path /api/github/webhooks` and point your webhook to the smee url th

The application runs on port 3000 by default, this can be customized with the `PORT` environment variable.

You can also use the npm script `npm run tunnel` which will run smee for you.

### Chart deployment

You can deploy this application to Kubernetes with the helm chart included in this repo:
Expand All @@ -69,6 +71,7 @@ See more in the [chart README](charts/github-comment-ops/README.md)

- `GITHUB_APP_ID`
- `GITHUB_APP_PRIVATE_KEY`
- Either the private key as a string or a file path prefixed by `file:`, e.g. `file:my-key.pem`
- `WEBHOOK_SECRET`

## Supported commands
Expand Down
11 changes: 8 additions & 3 deletions app/commands/close-command.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ import { closeMatcher } from "../matchers.js";
import { closeEnabled } from "../command-enabled.js";
import { closeIssue } from "../github.js";
import { getLogger } from "../logger.js";
import {
extractBody,
extractHtmlUrl,
extractLabelableId,
} from "../comment-extractor.js";

const classLogger = getLogger("commands/close-command");

Expand All @@ -12,7 +17,7 @@ export class CloseCommand extends Command {
}

matches() {
return closeMatcher(this.payload.comment.body);
return closeMatcher(extractBody(this.payload));
}

enabled(config) {
Expand All @@ -38,13 +43,13 @@ export class CloseCommand extends Command {
}

logger.info(
`Closing issue ${this.payload.issue.html_url}, reason: ${reason}`
`Closing issue ${extractHtmlUrl(this.payload)}, reason: ${reason}`
);
try {
await closeIssue(
authToken,
sourceRepo,
this.payload.issue.node_id,
extractLabelableId(this.payload),
reason
);
} catch (error) {
Expand Down
11 changes: 8 additions & 3 deletions app/commands/label-command.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ import { Command } from "./command.js";
import { extractCommaSeparated } from "../converters.js";

import { getLogger } from "../logger.js";
import {
extractBody,
extractHtmlUrl,
extractLabelableId,
} from "../comment-extractor.js";

const classLogger = getLogger("commands/label-command");

Expand All @@ -14,7 +19,7 @@ export class LabelCommand extends Command {
}

matches() {
return labelMatcher(this.payload.comment.body);
return labelMatcher(extractBody(this.payload));
}

enabled(config) {
Expand All @@ -32,14 +37,14 @@ export class LabelCommand extends Command {
});

logger.info(
`Labeling issue ${this.payload.issue.html_url} with labels ${labels}`
`Labeling issue ${extractHtmlUrl(this.payload)} with labels ${labels}`
);
try {
await addLabel(
authToken,
this.payload.repository.owner.login,
sourceRepo,
this.payload.issue.node_id,
extractLabelableId(this.payload),
labels
);
} catch (error) {
Expand Down
13 changes: 10 additions & 3 deletions app/commands/remove-label-command.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ import { removeLabel } from "../github.js";
import { Command } from "./command.js";
import { extractCommaSeparated } from "../converters.js";
import { getLogger } from "../logger.js";
import {
extractBody,
extractHtmlUrl,
extractLabelableId,
} from "../comment-extractor.js";

const classLogger = getLogger("commands/remove-label-command");

Expand All @@ -13,7 +18,7 @@ export class RemoveLabelCommand extends Command {
}

matches() {
return removeLabelMatcher(this.payload.comment.body);
return removeLabelMatcher(extractBody(this.payload));
}

enabled(config) {
Expand All @@ -31,14 +36,16 @@ export class RemoveLabelCommand extends Command {
});

logger.info(
`Removing label(s) from issue ${this.payload.issue.html_url}, labels ${labels}`
`Removing label(s) from issue ${extractHtmlUrl(
this.payload
)}, labels ${labels}`
);
try {
await removeLabel(
authToken,
this.payload.repository.owner.login,
sourceRepo,
this.payload.issue.node_id,
extractLabelableId(this.payload),
labels
);
} catch (error) {
Expand Down
15 changes: 12 additions & 3 deletions app/commands/reopen-command.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ import { reopenEnabled } from "../command-enabled.js";
import { reopenIssue } from "../github.js";
import { Command } from "./command.js";
import { getLogger } from "../logger.js";
import {
extractBody,
extractHtmlUrl,
extractLabelableId,
} from "../comment-extractor.js";

const classLogger = getLogger("commands/reopen-command");

Expand All @@ -12,7 +17,7 @@ export class ReopenCommand extends Command {
}

matches() {
return reopenMatcher(this.payload.comment.body);
return reopenMatcher(extractBody(this.payload));
}

enabled(config) {
Expand All @@ -32,10 +37,14 @@ export class ReopenCommand extends Command {
return;
}

logger.info(`Re-opening issue ${this.payload.issue.html_url}`);
logger.info(`Re-opening issue ${extractHtmlUrl(this.payload)}`);

try {
await reopenIssue(authToken, sourceRepo, this.payload.issue.node_id);
await reopenIssue(
authToken,
sourceRepo,
extractLabelableId(this.payload)
);
} catch (error) {
logger.error(
`Failed to reopen issue ${
Expand Down
13 changes: 10 additions & 3 deletions app/commands/reviewer-command.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ import { requestReviewers } from "../github.js";
import { Command } from "./command.js";
import { extractUsersAndTeams } from "../converters.js";
import { getLogger } from "../logger.js";
import {
extractBody,
extractHtmlUrl,
extractLabelableId,
} from "../comment-extractor.js";

const classLogger = getLogger("commands/reviewer-command");

Expand All @@ -13,7 +18,7 @@ export class ReviewerCommand extends Command {
}

matches() {
return reviewerMatcher(this.payload.comment.body);
return reviewerMatcher(extractBody(this.payload));
}

enabled(config) {
Expand All @@ -30,7 +35,9 @@ export class ReviewerCommand extends Command {
});

logger.info(
`Requesting review for ${reviewerMatches} at ${this.payload.issue.html_url}`
`Requesting review for ${reviewerMatches} at ${extractHtmlUrl(
this.payload
)}`
);
const reviewers = extractUsersAndTeams(
this.payload.repository.owner.login,
Expand All @@ -41,7 +48,7 @@ export class ReviewerCommand extends Command {
authToken,
this.payload.repository.owner.login,
sourceRepo,
this.payload.issue.node_id,
extractLabelableId(this.payload),
reviewers.users,
reviewers.teams
);
Expand Down
11 changes: 8 additions & 3 deletions app/commands/transfer-command.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ import { transferEnabled } from "../command-enabled.js";
import { transferIssue } from "../github.js";
import { Command } from "./command.js";
import { getLogger } from "../logger.js";
import {
extractBody,
extractHtmlUrl,
extractLabelableId,
} from "../comment-extractor.js";

const classLogger = getLogger("commands/transfer-command");

Expand All @@ -12,7 +17,7 @@ export class TransferCommand extends Command {
}

matches() {
return transferMatcher(this.payload.comment.body);
return transferMatcher(extractBody(this.payload));
}

enabled(config) {
Expand All @@ -29,15 +34,15 @@ export class TransferCommand extends Command {
});

logger.info(
`Transferring issue ${this.payload.issue.html_url} to repo ${targetRepo}`
`Transferring issue ${extractHtmlUrl(this.payload)} to repo ${targetRepo}`
);
try {
await transferIssue(
authToken,
this.payload.repository.owner.login,
sourceRepo,
targetRepo,
this.payload.issue.node_id
extractLabelableId(this.payload)
);
} catch (error) {
logger.error(
Expand Down
21 changes: 21 additions & 0 deletions app/comment-extractor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
export function extractBody(payload) {
if (payload.review) {
return payload.review.body;
}
return payload.comment.body;
}

export function extractHtmlUrl(payload) {
if (payload.review) {
return payload.pull_request.html_url;
}
return payload.issue.html_url;
}

export function extractLabelableId(payload) {
if (payload.review) {
return payload.pull_request.node_id;
}

return payload.issue.node_id;
}
79 changes: 79 additions & 0 deletions app/comment-extractor.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import {
extractBody,
extractHtmlUrl,
extractLabelableId,
} from "./comment-extractor.js";

describe("extractors", () => {
describe("extractBody", () => {
test("is a review", () => {
expect(
extractBody({
review: {
body: "review body",
},
})
).toEqual("review body");
});

test("is an issue", () => {
expect(
extractBody({
comment: {
body: "comment body",
},
})
).toEqual("comment body");
});
});

describe("extractHtmlUrl", () => {
test("is a review", () => {
expect(
extractHtmlUrl({
review: {
body: "review body",
},
pull_request: {
html_url: "https://github.com/some-org/some-repo/pull/1",
},
})
).toEqual("https://github.com/some-org/some-repo/pull/1");
});

test("is an issue", () => {
expect(
extractHtmlUrl({
issue: {
html_url: "https://github.com/some-org/some-repo/issue/1",
},
})
).toEqual("https://github.com/some-org/some-repo/issue/1");
});
});

describe("extractLabelableId", () => {
test("is a review", () => {
expect(
extractLabelableId({
review: {
body: "review body",
},
pull_request: {
node_id: "PR_aaaaaa",
},
})
).toEqual("PR_aaaaaa");
});

test("is an issue", () => {
expect(
extractLabelableId({
issue: {
node_id: "PR_abcdefgh",
},
})
).toEqual("PR_abcdefgh");
});
});
});
13 changes: 11 additions & 2 deletions app/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { getCommands } from "./commands.js";
const OctokitConfig = Octokit.plugin(octoKitConfig);

import { getLogger } from "./logger.js";
import { extractLabelableId } from "./comment-extractor.js";

const classLogger = getLogger("router");

Expand All @@ -30,7 +31,7 @@ export async function router(auth, id, payload, verbose) {
const octokit = new OctokitConfig({ auth: authToken });

try {
await addReaction(authToken, payload.comment.node_id, "THUMBS_UP");
await addReaction(authToken, getCommentNodeId(payload), "THUMBS_UP");
} catch (error) {
logger.error(
`Failed to add reaction ${
Expand All @@ -54,9 +55,17 @@ export async function router(auth, id, payload, verbose) {
const result = command.enabled(config);
await (result.enabled
? command.run(authToken)
: reportError(authToken, payload.issue.node_id, result.error));
: reportError(authToken, extractLabelableId(payload), result.error));
}
} catch (error) {
logger.error(error);
}
}

function getCommentNodeId(payload) {
if (payload.review) {
return payload.review.node_id;
}

return payload.comment.node_id;
}
Loading

0 comments on commit b74c409

Please sign in to comment.