-
Notifications
You must be signed in to change notification settings - Fork 88
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[bots] Bot to comment wiki link on codev PRs with no write permissions (
#5027) Comments on PRs in pytorch/pytorch that look like they were exported from phab but the author doesn't have write permissions. Changed check for Differential Revision string to also take ones that have markdown links (like `[D11111](link)`) I've seen them around, I think they're usually ghstack/stacked diff PRs
- Loading branch information
Showing
6 changed files
with
164 additions
and
37 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { hasWritePermissions, isPyTorchPyTorch } from "./utils"; | ||
import { Probot } from "probot"; | ||
|
||
export const CODEV_INDICATOR = /Differential Revision: \[?D/; | ||
const CODEV_WIKI_LINK = | ||
"https://www.internalfb.com/intern/wiki/PyTorch/PyTorchDev/Workflow/develop/#setup-your-github-accoun"; | ||
|
||
export function genCodevNoWritePermComment(author: string) { | ||
return ( | ||
"This appears to be a diff that was exported from phabricator, " + | ||
`but the PR author does not have sufficient permissions to run CI. ` + | ||
`@${author}, please do step 2 of [internal wiki](${CODEV_WIKI_LINK}) to get write access so ` + | ||
`you do not need to get CI approvals in the future. ` + | ||
"If you think this is a mistake, please contact the Pytorch Dev Infra team." | ||
); | ||
} | ||
|
||
// If a pytorch/pytorch codev PR is created but the author doesn't have write | ||
// permissions, the bot will comment on the PR to inform the author to get write | ||
// access. | ||
export default function codevNoWritePerm(app: Probot): void { | ||
app.on("pull_request.opened", async (context) => { | ||
const body = context.payload.pull_request.body; | ||
const author = context.payload.pull_request.user.login; | ||
const prNumber = context.payload.pull_request.number; | ||
const owner = context.payload.repository.owner.login; | ||
const repo = context.payload.repository.name; | ||
if ( | ||
isPyTorchPyTorch(owner, repo) && | ||
body?.match(CODEV_INDICATOR) && | ||
!(await hasWritePermissions(context, author)) | ||
) { | ||
await context.octokit.rest.issues.createComment({ | ||
owner, | ||
repo, | ||
issue_number: prNumber, | ||
body: genCodevNoWritePermComment(author), | ||
}); | ||
} | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import nock from "nock"; | ||
import * as utils from "./utils"; | ||
import myProbotApp from "../lib/bot/codevNoWritePermBot"; | ||
import { handleScope, requireDeepCopy } from "./common"; | ||
import { Probot } from "probot"; | ||
import * as botUtils from "lib/bot/utils"; | ||
|
||
nock.disableNetConnect(); | ||
|
||
describe("codevNoWritePermBot", () => { | ||
let probot: Probot; | ||
|
||
beforeEach(() => { | ||
probot = utils.testProbot(); | ||
probot.load(myProbotApp); | ||
nock("https://api.github.com") | ||
.post("/app/installations/2/access_tokens") | ||
.reply(200, { token: "test" }); | ||
}); | ||
|
||
afterEach(() => { | ||
jest.restoreAllMocks(); | ||
nock.cleanAll(); | ||
}); | ||
|
||
function mockIsPytorchPytorch(bool: boolean) { | ||
return jest.spyOn(botUtils, "isPyTorchPyTorch").mockReturnValue(bool); | ||
} | ||
|
||
test("ignore non pytorch/pytorch PR", async () => { | ||
const payload = requireDeepCopy("./fixtures/pull_request.opened"); | ||
payload.payload.pull_request.body = "Differential Revision: D123123123"; | ||
mockIsPytorchPytorch(false); | ||
await probot.receive(payload); | ||
}); | ||
|
||
test("ignore pytorch/pytorch PR that is not codev", async () => { | ||
const payload = requireDeepCopy("./fixtures/pull_request.opened"); | ||
mockIsPytorchPytorch(true); | ||
payload.payload.pull_request.body = "This is not a codev PR"; | ||
await probot.receive(payload); | ||
}); | ||
|
||
test("do not comment if has write perms", async () => { | ||
const payload = requireDeepCopy("./fixtures/pull_request.opened"); | ||
payload.payload.pull_request.body = "Differential Revision: D123123123"; | ||
const repoFullName = payload.payload.repository.full_name; | ||
const author = payload.payload.pull_request.user.login; | ||
mockIsPytorchPytorch(true); | ||
const scope = utils.mockPermissions(repoFullName, author, "write"); | ||
await probot.receive(payload); | ||
handleScope(scope); | ||
}); | ||
|
||
test("comment if no write perms", async () => { | ||
const payload = requireDeepCopy("./fixtures/pull_request.opened"); | ||
payload.payload.pull_request.body = "Differential Revision: D123123123"; | ||
const repoFullName = payload.payload.repository.full_name; | ||
const author = payload.payload.pull_request.user.login; | ||
mockIsPytorchPytorch(true); | ||
const scopes = [ | ||
utils.mockPermissions(repoFullName, author, "read"), | ||
utils.mockPostComment(repoFullName, 31, [ | ||
`This appears to be a diff that was exported from phabricator`, | ||
]), | ||
]; | ||
await probot.receive(payload); | ||
handleScope(scopes); | ||
}); | ||
|
||
test("comment if no write perms, alternate magic string", async () => { | ||
// Same as the previous test, but with a different body | ||
const payload = requireDeepCopy("./fixtures/pull_request.opened"); | ||
payload.payload.pull_request.body = | ||
"Differential Revision: [D123123123](Link)"; | ||
const repoFullName = payload.payload.repository.full_name; | ||
const author = payload.payload.pull_request.user.login; | ||
mockIsPytorchPytorch(true); | ||
const scopes = [ | ||
utils.mockPermissions(repoFullName, author, "read"), | ||
utils.mockPostComment(repoFullName, 31, [ | ||
`This appears to be a diff that was exported from phabricator`, | ||
]), | ||
]; | ||
await probot.receive(payload); | ||
handleScope(scopes); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters