From cca496c96c1958992f92f8685a4ae2d8d6527bd6 Mon Sep 17 00:00:00 2001 From: Anh Le Date: Wed, 17 Nov 2021 13:56:28 +1100 Subject: [PATCH] Post a warning if comment has preamble (#25) --- .../create_comment_body_expected_warning.json | 3 ++ .../github/create_comment_warning.json | 28 ++++++++++ .../lambda_request_has_emoji.json | 53 +++++++++++++++++++ .../lambda_request_match_preamble.json | 53 +++++++++++++++++++ __tests__/index.spec.ts | 44 +++++++++++++++ src/events/commented.ts | 31 +++++++++-- src/events/pr_opened.ts | 2 +- src/github.ts | 11 ++-- src/trigger.ts | 9 ++++ 9 files changed, 220 insertions(+), 14 deletions(-) create mode 100644 __tests__/fixtures/issue_comment/github/create_comment_body_expected_warning.json create mode 100644 __tests__/fixtures/issue_comment/github/create_comment_warning.json create mode 100644 __tests__/fixtures/issue_comment/lambda_request_has_emoji.json create mode 100644 __tests__/fixtures/issue_comment/lambda_request_match_preamble.json diff --git a/__tests__/fixtures/issue_comment/github/create_comment_body_expected_warning.json b/__tests__/fixtures/issue_comment/github/create_comment_body_expected_warning.json new file mode 100644 index 0000000..7970c63 --- /dev/null +++ b/__tests__/fixtures/issue_comment/github/create_comment_body_expected_warning.json @@ -0,0 +1,3 @@ +{ + "body": "Your last comment looked similar to a command but Rocketbot couldn't understand it. Were you trying to [run a build](https://github.com/canva-public/rocketbot/blob/main/docs/getting-started.md#run-a-build)?" +} diff --git a/__tests__/fixtures/issue_comment/github/create_comment_warning.json b/__tests__/fixtures/issue_comment/github/create_comment_warning.json new file mode 100644 index 0000000..400fa56 --- /dev/null +++ b/__tests__/fixtures/issue_comment/github/create_comment_warning.json @@ -0,0 +1,28 @@ +{ + "url": "https://api.github.com/repos/some-org/some-repo/issues/comments/1111111", + "html_url": "https://github.com/some-org/some-repo/pull/1111111#issuecomment-280987786", + "issue_url": "https://api.github.com/repos/some-org/some-repo/issues/1111111", + "id": 280987786, + "user": { + "login": "some-user", + "id": 11111111, + "avatar_url": "https://avatars.githubusercontent.com/u/11111111?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/some-user", + "html_url": "https://github.com/some-user", + "followers_url": "https://api.github.com/users/some-user/followers", + "following_url": "https://api.github.com/users/some-user/following{/other_user}", + "gists_url": "https://api.github.com/users/some-user/gists{/gist_id}", + "starred_url": "https://api.github.com/users/some-user/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/some-user/subscriptions", + "organizations_url": "https://api.github.com/users/some-user/orgs", + "repos_url": "https://api.github.com/users/some-user/repos", + "events_url": "https://api.github.com/users/some-user/events{/privacy}", + "received_events_url": "https://api.github.com/users/some-user/received_events", + "type": "User", + "site_admin": false + }, + "created_at": "2017-02-20T04:53:38Z", + "updated_at": "2017-02-20T04:53:38Z", + "body": "Your last comment looked similar to a command but Rocketbot couldn't understand it. Were you trying to [run a build](https://github.com/canva-public/rocketbot/blob/main/docs/getting-started.md#run-a-build)?" +} diff --git a/__tests__/fixtures/issue_comment/lambda_request_has_emoji.json b/__tests__/fixtures/issue_comment/lambda_request_has_emoji.json new file mode 100644 index 0000000..bd6e552 --- /dev/null +++ b/__tests__/fixtures/issue_comment/lambda_request_has_emoji.json @@ -0,0 +1,53 @@ +{ + "resource": "/StartBuildKiteBuild", + "path": "/StartBuildKiteBuild", + "httpMethod": "POST", + "headers": { + "Accept": "*/*", + "CloudFront-Forwarded-Proto": "https", + "CloudFront-Is-Desktop-Viewer": "true", + "CloudFront-Is-Mobile-Viewer": "false", + "CloudFront-Is-SmartTV-Viewer": "false", + "CloudFront-Is-Tablet-Viewer": "false", + "CloudFront-Viewer-Country": "US", + "content-type": "application/json", + "Host": "xxxxxxxxxx.execute-api.us-east-1.amazonaws.com", + "User-Agent": "GitHub-Hookshot/886c556", + "Via": "1.1 8008015354a3ca72f56c382a1d1cfe9f.cloudfront.net (CloudFront)", + "X-Amz-Cf-Id": "HgjErOsJdhxutD-z-u08qkaYI3Tx6-IFVsEjwS5N3YmNWq66ZNmhrw==", + "X-Amzn-Trace-Id": "Root=1-58a3f60a-4bc956ce51375773441fc28d", + "X-Forwarded-For": "192.30.252.45, 54.239.134.103", + "X-Forwarded-Port": "443", + "X-Forwarded-Proto": "https", + "X-GitHub-Delivery": "8d962100-f348-11e6-9863-89383323f38a", + "X-GitHub-Event": "issue_comment" + }, + "queryStringParameters": null, + "pathParameters": null, + "stageVariables": null, + "requestContext": { + "accountId": "111111100000", + "resourceId": "m4cq3t", + "stage": "prod", + "requestId": "8e016671-f348-11e6-91e9-b966b3b9522f", + "identity": { + "cognitoIdentityPoolId": null, + "accountId": null, + "cognitoIdentityId": null, + "caller": null, + "apiKey": null, + "sourceIp": "192.30.252.45", + "accessKey": null, + "cognitoAuthenticationType": null, + "cognitoAuthenticationProvider": null, + "userArn": null, + "userAgent": "GitHub-Hookshot/886c556", + "user": null + }, + "resourcePath": "/StartBuildKiteBuild", + "httpMethod": "POST", + "apiId": "hgcoqhi9i5" + }, + "body": "{\"action\":\"created\",\"issue\":{\"url\":\"https://api.github.com/repos/some-org/some-repo/issues/9500\",\"repository_url\":\"https://api.github.com/repos/some-org/some-repo\",\"labels_url\":\"https://api.github.com/repos/some-org/some-repo/issues/9500/labels{/name}\",\"comments_url\":\"https://api.github.com/repos/some-org/some-repo/issues/9500/comments\",\"events_url\":\"https://api.github.com/repos/some-org/some-repo/issues/9500/events\",\"html_url\":\"https://github.com/some-org/some-repo/pull/9500\",\"id\":206679442,\"number\":9500,\"title\":\"test\",\"user\":{\"login\":\"some-user\",\"id\":111111,\"avatar_url\":\"https://avatars.githubusercontent.com/u/111111?v=3\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/some-user\",\"html_url\":\"https://github.com/some-user\",\"followers_url\":\"https://api.github.com/users/some-user/followers\",\"following_url\":\"https://api.github.com/users/some-user/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/some-user/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/some-user/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/some-user/subscriptions\",\"organizations_url\":\"https://api.github.com/users/some-user/orgs\",\"repos_url\":\"https://api.github.com/users/some-user/repos\",\"events_url\":\"https://api.github.com/users/some-user/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/some-user/received_events\",\"type\":\"User\",\"site_admin\":false},\"labels\":[],\"state\":\"open\",\"locked\":false,\"assignee\":null,\"assignees\":[],\"milestone\":null,\"comments\":27,\"created_at\":\"2017-02-10T01:15:00Z\",\"updated_at\":\"2017-02-15T06:32:42Z\",\"closed_at\":null,\"pull_request\":{\"url\":\"https://api.github.com/repos/some-org/some-repo/pulls/9500\",\"html_url\":\"https://github.com/some-org/some-repo/pull/9500\",\"diff_url\":\"https://github.com/some-org/some-repo/pull/9500.diff\",\"patch_url\":\"https://github.com/some-org/some-repo/pull/9500.patch\"},\"body\":\"This is a test for the github-control bot.\\r\\n\\r\\nEdited\"},\"comment\":{\"url\":\"https://api.github.com/repos/some-org/some-repo/issues/comments/1111111\",\"html_url\":\"https://github.com/some-org/some-repo/pull/9500#issuecomment-279928810\",\"issue_url\":\"https://api.github.com/repos/some-org/some-repo/issues/9500\",\"id\":279928810,\"user\":{\"login\":\"some-user\",\"id\":111111,\"avatar_url\":\"https://avatars.githubusercontent.com/u/111111?v=3\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/some-user\",\"html_url\":\"https://github.com/some-user\",\"followers_url\":\"https://api.github.com/users/some-user/followers\",\"following_url\":\"https://api.github.com/users/some-user/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/some-user/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/some-user/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/some-user/subscriptions\",\"organizations_url\":\"https://api.github.com/users/some-user/orgs\",\"repos_url\":\"https://api.github.com/users/some-user/repos\",\"events_url\":\"https://api.github.com/users/some-user/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/some-user/received_events\",\"type\":\"User\",\"site_admin\":false},\"created_at\":\"2017-02-15T06:32:42Z\",\"updated_at\":\"2017-02-15T06:32:42Z\",\"body\":\"I'm an emoji connoisseur so I put the :rocket: emoji everywhere\"},\"repository\":{\"id\":1111111,\"name\":\"some-repo\",\"full_name\":\"some-org/some-repo\",\"owner\":{\"login\":\"some-org\",\"id\":1111111,\"avatar_url\":\"https://avatars.githubusercontent.com/u/1111111?v=3\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/some-org\",\"html_url\":\"https://github.com/some-org\",\"followers_url\":\"https://api.github.com/users/some-org/followers\",\"following_url\":\"https://api.github.com/users/some-org/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/some-org/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/some-org/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/some-org/subscriptions\",\"organizations_url\":\"https://api.github.com/users/some-org/orgs\",\"repos_url\":\"https://api.github.com/users/some-org/repos\",\"events_url\":\"https://api.github.com/users/some-org/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/some-org/received_events\",\"type\":\"Organization\",\"site_admin\":false},\"private\":true,\"html_url\":\"https://github.com/some-org/some-repo\",\"description\":\"Some description\",\"fork\":false,\"url\":\"https://api.github.com/repos/some-org/some-repo\",\"forks_url\":\"https://api.github.com/repos/some-org/some-repo/forks\",\"keys_url\":\"https://api.github.com/repos/some-org/some-repo/keys{/key_id}\",\"collaborators_url\":\"https://api.github.com/repos/some-org/some-repo/collaborators{/collaborator}\",\"teams_url\":\"https://api.github.com/repos/some-org/some-repo/teams\",\"hooks_url\":\"https://api.github.com/repos/some-org/some-repo/hooks\",\"issue_events_url\":\"https://api.github.com/repos/some-org/some-repo/issues/events{/number}\",\"events_url\":\"https://api.github.com/repos/some-org/some-repo/events\",\"assignees_url\":\"https://api.github.com/repos/some-org/some-repo/assignees{/user}\",\"branches_url\":\"https://api.github.com/repos/some-org/some-repo/branches{/branch}\",\"tags_url\":\"https://api.github.com/repos/some-org/some-repo/tags\",\"blobs_url\":\"https://api.github.com/repos/some-org/some-repo/git/blobs{/sha}\",\"git_tags_url\":\"https://api.github.com/repos/some-org/some-repo/git/tags{/sha}\",\"git_refs_url\":\"https://api.github.com/repos/some-org/some-repo/git/refs{/sha}\",\"trees_url\":\"https://api.github.com/repos/some-org/some-repo/git/trees{/sha}\",\"statuses_url\":\"https://api.github.com/repos/some-org/some-repo/statuses/{sha}\",\"languages_url\":\"https://api.github.com/repos/some-org/some-repo/languages\",\"stargazers_url\":\"https://api.github.com/repos/some-org/some-repo/stargazers\",\"contributors_url\":\"https://api.github.com/repos/some-org/some-repo/contributors\",\"subscribers_url\":\"https://api.github.com/repos/some-org/some-repo/subscribers\",\"subscription_url\":\"https://api.github.com/repos/some-org/some-repo/subscription\",\"commits_url\":\"https://api.github.com/repos/some-org/some-repo/commits{/sha}\",\"git_commits_url\":\"https://api.github.com/repos/some-org/some-repo/git/commits{/sha}\",\"comments_url\":\"https://api.github.com/repos/some-org/some-repo/comments{/number}\",\"issue_comment_url\":\"https://api.github.com/repos/some-org/some-repo/issues/comments{/number}\",\"contents_url\":\"https://api.github.com/repos/some-org/some-repo/contents/{+path}\",\"compare_url\":\"https://api.github.com/repos/some-org/some-repo/compare/{base}...{head}\",\"merges_url\":\"https://api.github.com/repos/some-org/some-repo/merges\",\"archive_url\":\"https://api.github.com/repos/some-org/some-repo/{archive_format}{/ref}\",\"downloads_url\":\"https://api.github.com/repos/some-org/some-repo/downloads\",\"issues_url\":\"https://api.github.com/repos/some-org/some-repo/issues{/number}\",\"pulls_url\":\"https://api.github.com/repos/some-org/some-repo/pulls{/number}\",\"milestones_url\":\"https://api.github.com/repos/some-org/some-repo/milestones{/number}\",\"notifications_url\":\"https://api.github.com/repos/some-org/some-repo/notifications{?since,all,participating}\",\"labels_url\":\"https://api.github.com/repos/some-org/some-repo/labels{/name}\",\"releases_url\":\"https://api.github.com/repos/some-org/some-repo/releases{/id}\",\"deployments_url\":\"https://api.github.com/repos/some-org/some-repo/deployments\",\"created_at\":\"2012-10-15T08:14:27Z\",\"updated_at\":\"2017-02-05T22:21:39Z\",\"pushed_at\":\"2017-02-15T06:25:23Z\",\"git_url\":\"git://github.com/some-org/some-repo.git\",\"ssh_url\":\"git@github.com:some-org/some-repo.git\",\"clone_url\":\"https://github.com/some-org/some-repo.git\",\"svn_url\":\"https://github.com/some-org/some-repo\",\"homepage\":\"\",\"size\":375432,\"stargazers_count\":9,\"watchers_count\":9,\"language\":\"JavaScript\",\"has_issues\":false,\"has_downloads\":true,\"has_wiki\":false,\"has_pages\":false,\"forks_count\":0,\"mirror_url\":null,\"open_issues_count\":349,\"forks\":0,\"open_issues\":349,\"watchers\":9,\"default_branch\":\"master\"},\"organization\":{\"login\":\"some-org\",\"id\":1111111,\"url\":\"https://api.github.com/orgs/Canva\",\"repos_url\":\"https://api.github.com/orgs/some-org/repos\",\"events_url\":\"https://api.github.com/orgs/some-org/events\",\"hooks_url\":\"https://api.github.com/orgs/some-org/hooks\",\"issues_url\":\"https://api.github.com/orgs/some-org/issues\",\"members_url\":\"https://api.github.com/orgs/some-org/members{/member}\",\"public_members_url\":\"https://api.github.com/orgs/some-org/public_members{/member}\",\"avatar_url\":\"https://avatars.githubusercontent.com/u/1111111?v=3\",\"description\":null},\"sender\":{\"login\":\"some-user\",\"id\":111111,\"avatar_url\":\"https://avatars.githubusercontent.com/u/111111?v=3\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/some-user\",\"html_url\":\"https://github.com/some-user\",\"followers_url\":\"https://api.github.com/users/some-user/followers\",\"following_url\":\"https://api.github.com/users/some-user/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/some-user/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/some-user/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/some-user/subscriptions\",\"organizations_url\":\"https://api.github.com/users/some-user/orgs\",\"repos_url\":\"https://api.github.com/users/some-user/repos\",\"events_url\":\"https://api.github.com/users/some-user/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/some-user/received_events\",\"type\":\"User\",\"site_admin\":false}}", + "isBase64Encoded": false +} diff --git a/__tests__/fixtures/issue_comment/lambda_request_match_preamble.json b/__tests__/fixtures/issue_comment/lambda_request_match_preamble.json new file mode 100644 index 0000000..07df8d0 --- /dev/null +++ b/__tests__/fixtures/issue_comment/lambda_request_match_preamble.json @@ -0,0 +1,53 @@ +{ + "resource": "/StartBuildKiteBuild", + "path": "/StartBuildKiteBuild", + "httpMethod": "POST", + "headers": { + "Accept": "*/*", + "CloudFront-Forwarded-Proto": "https", + "CloudFront-Is-Desktop-Viewer": "true", + "CloudFront-Is-Mobile-Viewer": "false", + "CloudFront-Is-SmartTV-Viewer": "false", + "CloudFront-Is-Tablet-Viewer": "false", + "CloudFront-Viewer-Country": "US", + "content-type": "application/json", + "Host": "xxxxxxxxxx.execute-api.us-east-1.amazonaws.com", + "User-Agent": "GitHub-Hookshot/886c556", + "Via": "1.1 8008015354a3ca72f56c382a1d1cfe9f.cloudfront.net (CloudFront)", + "X-Amz-Cf-Id": "HgjErOsJdhxutD-z-u08qkaYI3Tx6-IFVsEjwS5N3YmNWq66ZNmhrw==", + "X-Amzn-Trace-Id": "Root=1-58a3f60a-4bc956ce51375773441fc28d", + "X-Forwarded-For": "192.30.252.45, 54.239.134.103", + "X-Forwarded-Port": "443", + "X-Forwarded-Proto": "https", + "X-GitHub-Delivery": "8d962100-f348-11e6-9863-89383323f38a", + "X-GitHub-Event": "issue_comment" + }, + "queryStringParameters": null, + "pathParameters": null, + "stageVariables": null, + "requestContext": { + "accountId": "111111100000", + "resourceId": "m4cq3t", + "stage": "prod", + "requestId": "8e016671-f348-11e6-91e9-b966b3b9522f", + "identity": { + "cognitoIdentityPoolId": null, + "accountId": null, + "cognitoIdentityId": null, + "caller": null, + "apiKey": null, + "sourceIp": "192.30.252.45", + "accessKey": null, + "cognitoAuthenticationType": null, + "cognitoAuthenticationProvider": null, + "userArn": null, + "userAgent": "GitHub-Hookshot/886c556", + "user": null + }, + "resourcePath": "/StartBuildKiteBuild", + "httpMethod": "POST", + "apiId": "hgcoqhi9i5" + }, + "body": "{\"action\":\"created\",\"issue\":{\"url\":\"https://api.github.com/repos/some-org/some-repo/issues/9500\",\"repository_url\":\"https://api.github.com/repos/some-org/some-repo\",\"labels_url\":\"https://api.github.com/repos/some-org/some-repo/issues/9500/labels{/name}\",\"comments_url\":\"https://api.github.com/repos/some-org/some-repo/issues/9500/comments\",\"events_url\":\"https://api.github.com/repos/some-org/some-repo/issues/9500/events\",\"html_url\":\"https://github.com/some-org/some-repo/pull/9500\",\"id\":206679442,\"number\":9500,\"title\":\"test\",\"user\":{\"login\":\"some-user\",\"id\":111111,\"avatar_url\":\"https://avatars.githubusercontent.com/u/111111?v=3\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/some-user\",\"html_url\":\"https://github.com/some-user\",\"followers_url\":\"https://api.github.com/users/some-user/followers\",\"following_url\":\"https://api.github.com/users/some-user/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/some-user/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/some-user/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/some-user/subscriptions\",\"organizations_url\":\"https://api.github.com/users/some-user/orgs\",\"repos_url\":\"https://api.github.com/users/some-user/repos\",\"events_url\":\"https://api.github.com/users/some-user/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/some-user/received_events\",\"type\":\"User\",\"site_admin\":false},\"labels\":[],\"state\":\"open\",\"locked\":false,\"assignee\":null,\"assignees\":[],\"milestone\":null,\"comments\":27,\"created_at\":\"2017-02-10T01:15:00Z\",\"updated_at\":\"2017-02-15T06:32:42Z\",\"closed_at\":null,\"pull_request\":{\"url\":\"https://api.github.com/repos/some-org/some-repo/pulls/9500\",\"html_url\":\"https://github.com/some-org/some-repo/pull/9500\",\"diff_url\":\"https://github.com/some-org/some-repo/pull/9500.diff\",\"patch_url\":\"https://github.com/some-org/some-repo/pull/9500.patch\"},\"body\":\"This is a test for the github-control bot.\\r\\n\\r\\nEdited\"},\"comment\":{\"url\":\"https://api.github.com/repos/some-org/some-repo/issues/comments/1111111\",\"html_url\":\"https://github.com/some-org/some-repo/pull/9500#issuecomment-279928810\",\"issue_url\":\"https://api.github.com/repos/some-org/some-repo/issues/9500\",\"id\":279928810,\"user\":{\"login\":\"some-user\",\"id\":111111,\"avatar_url\":\"https://avatars.githubusercontent.com/u/111111?v=3\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/some-user\",\"html_url\":\"https://github.com/some-user\",\"followers_url\":\"https://api.github.com/users/some-user/followers\",\"following_url\":\"https://api.github.com/users/some-user/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/some-user/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/some-user/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/some-user/subscriptions\",\"organizations_url\":\"https://api.github.com/users/some-user/orgs\",\"repos_url\":\"https://api.github.com/users/some-user/repos\",\"events_url\":\"https://api.github.com/users/some-user/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/some-user/received_events\",\"type\":\"User\",\"site_admin\":false},\"created_at\":\"2017-02-15T06:32:42Z\",\"updated_at\":\"2017-02-15T06:32:42Z\",\"body\":\":rocket: some-pipeline-lite\"},\"repository\":{\"id\":1111111,\"name\":\"some-repo\",\"full_name\":\"some-org/some-repo\",\"owner\":{\"login\":\"some-org\",\"id\":1111111,\"avatar_url\":\"https://avatars.githubusercontent.com/u/1111111?v=3\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/some-org\",\"html_url\":\"https://github.com/some-org\",\"followers_url\":\"https://api.github.com/users/some-org/followers\",\"following_url\":\"https://api.github.com/users/some-org/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/some-org/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/some-org/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/some-org/subscriptions\",\"organizations_url\":\"https://api.github.com/users/some-org/orgs\",\"repos_url\":\"https://api.github.com/users/some-org/repos\",\"events_url\":\"https://api.github.com/users/some-org/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/some-org/received_events\",\"type\":\"Organization\",\"site_admin\":false},\"private\":true,\"html_url\":\"https://github.com/some-org/some-repo\",\"description\":\"Some description\",\"fork\":false,\"url\":\"https://api.github.com/repos/some-org/some-repo\",\"forks_url\":\"https://api.github.com/repos/some-org/some-repo/forks\",\"keys_url\":\"https://api.github.com/repos/some-org/some-repo/keys{/key_id}\",\"collaborators_url\":\"https://api.github.com/repos/some-org/some-repo/collaborators{/collaborator}\",\"teams_url\":\"https://api.github.com/repos/some-org/some-repo/teams\",\"hooks_url\":\"https://api.github.com/repos/some-org/some-repo/hooks\",\"issue_events_url\":\"https://api.github.com/repos/some-org/some-repo/issues/events{/number}\",\"events_url\":\"https://api.github.com/repos/some-org/some-repo/events\",\"assignees_url\":\"https://api.github.com/repos/some-org/some-repo/assignees{/user}\",\"branches_url\":\"https://api.github.com/repos/some-org/some-repo/branches{/branch}\",\"tags_url\":\"https://api.github.com/repos/some-org/some-repo/tags\",\"blobs_url\":\"https://api.github.com/repos/some-org/some-repo/git/blobs{/sha}\",\"git_tags_url\":\"https://api.github.com/repos/some-org/some-repo/git/tags{/sha}\",\"git_refs_url\":\"https://api.github.com/repos/some-org/some-repo/git/refs{/sha}\",\"trees_url\":\"https://api.github.com/repos/some-org/some-repo/git/trees{/sha}\",\"statuses_url\":\"https://api.github.com/repos/some-org/some-repo/statuses/{sha}\",\"languages_url\":\"https://api.github.com/repos/some-org/some-repo/languages\",\"stargazers_url\":\"https://api.github.com/repos/some-org/some-repo/stargazers\",\"contributors_url\":\"https://api.github.com/repos/some-org/some-repo/contributors\",\"subscribers_url\":\"https://api.github.com/repos/some-org/some-repo/subscribers\",\"subscription_url\":\"https://api.github.com/repos/some-org/some-repo/subscription\",\"commits_url\":\"https://api.github.com/repos/some-org/some-repo/commits{/sha}\",\"git_commits_url\":\"https://api.github.com/repos/some-org/some-repo/git/commits{/sha}\",\"comments_url\":\"https://api.github.com/repos/some-org/some-repo/comments{/number}\",\"issue_comment_url\":\"https://api.github.com/repos/some-org/some-repo/issues/comments{/number}\",\"contents_url\":\"https://api.github.com/repos/some-org/some-repo/contents/{+path}\",\"compare_url\":\"https://api.github.com/repos/some-org/some-repo/compare/{base}...{head}\",\"merges_url\":\"https://api.github.com/repos/some-org/some-repo/merges\",\"archive_url\":\"https://api.github.com/repos/some-org/some-repo/{archive_format}{/ref}\",\"downloads_url\":\"https://api.github.com/repos/some-org/some-repo/downloads\",\"issues_url\":\"https://api.github.com/repos/some-org/some-repo/issues{/number}\",\"pulls_url\":\"https://api.github.com/repos/some-org/some-repo/pulls{/number}\",\"milestones_url\":\"https://api.github.com/repos/some-org/some-repo/milestones{/number}\",\"notifications_url\":\"https://api.github.com/repos/some-org/some-repo/notifications{?since,all,participating}\",\"labels_url\":\"https://api.github.com/repos/some-org/some-repo/labels{/name}\",\"releases_url\":\"https://api.github.com/repos/some-org/some-repo/releases{/id}\",\"deployments_url\":\"https://api.github.com/repos/some-org/some-repo/deployments\",\"created_at\":\"2012-10-15T08:14:27Z\",\"updated_at\":\"2017-02-05T22:21:39Z\",\"pushed_at\":\"2017-02-15T06:25:23Z\",\"git_url\":\"git://github.com/some-org/some-repo.git\",\"ssh_url\":\"git@github.com:some-org/some-repo.git\",\"clone_url\":\"https://github.com/some-org/some-repo.git\",\"svn_url\":\"https://github.com/some-org/some-repo\",\"homepage\":\"\",\"size\":375432,\"stargazers_count\":9,\"watchers_count\":9,\"language\":\"JavaScript\",\"has_issues\":false,\"has_downloads\":true,\"has_wiki\":false,\"has_pages\":false,\"forks_count\":0,\"mirror_url\":null,\"open_issues_count\":349,\"forks\":0,\"open_issues\":349,\"watchers\":9,\"default_branch\":\"master\"},\"organization\":{\"login\":\"some-org\",\"id\":1111111,\"url\":\"https://api.github.com/orgs/Canva\",\"repos_url\":\"https://api.github.com/orgs/some-org/repos\",\"events_url\":\"https://api.github.com/orgs/some-org/events\",\"hooks_url\":\"https://api.github.com/orgs/some-org/hooks\",\"issues_url\":\"https://api.github.com/orgs/some-org/issues\",\"members_url\":\"https://api.github.com/orgs/some-org/members{/member}\",\"public_members_url\":\"https://api.github.com/orgs/some-org/public_members{/member}\",\"avatar_url\":\"https://avatars.githubusercontent.com/u/1111111?v=3\",\"description\":null},\"sender\":{\"login\":\"some-user\",\"id\":111111,\"avatar_url\":\"https://avatars.githubusercontent.com/u/111111?v=3\",\"gravatar_id\":\"\",\"url\":\"https://api.github.com/users/some-user\",\"html_url\":\"https://github.com/some-user\",\"followers_url\":\"https://api.github.com/users/some-user/followers\",\"following_url\":\"https://api.github.com/users/some-user/following{/other_user}\",\"gists_url\":\"https://api.github.com/users/some-user/gists{/gist_id}\",\"starred_url\":\"https://api.github.com/users/some-user/starred{/owner}{/repo}\",\"subscriptions_url\":\"https://api.github.com/users/some-user/subscriptions\",\"organizations_url\":\"https://api.github.com/users/some-user/orgs\",\"repos_url\":\"https://api.github.com/users/some-user/repos\",\"events_url\":\"https://api.github.com/users/some-user/events{/privacy}\",\"received_events_url\":\"https://api.github.com/users/some-user/received_events\",\"type\":\"User\",\"site_admin\":false}}", + "isBase64Encoded": false +} diff --git a/__tests__/index.spec.ts b/__tests__/index.spec.ts index 25b949e..09d3e52 100644 --- a/__tests__/index.spec.ts +++ b/__tests__/index.spec.ts @@ -890,6 +890,50 @@ describe('github-control', () => { }); assertNockDone(); }); + + it('should post a warning if the comment looks similar to a command', async () => { + expect.hasAssertions(); + const lambdaRequest = loadFixture( + 'issue_comment/lambda_request_match_preamble', + ); + const createCommentReply = loadFixture( + 'issue_comment/github/create_comment_warning', + ); + const expectedGithubCreateCommentBody = loadFixture( + 'issue_comment/github/create_comment_body_expected_warning', + ); + + nock('https://api.github.com') + .post( + '/repos/some-org/some-repo/issues/9500/comments', + expectedGithubCreateCommentBody, + ) + .reply(200, createCommentReply); + + const res = await handler(lambdaRequest, context); + assertLambdaResponse(res, 200, { + success: true, + triggered: false, + commented: true, + commentUrl: + 'https://github.com/some-org/some-repo/pull/1111111#issuecomment-280987786', + }); + assertNockDone(); + }); + + it('should not post a warning if the comment has a rocket emoji', async () => { + expect.hasAssertions(); + const lambdaRequest = loadFixture( + 'issue_comment/lambda_request_has_emoji', + ); + + const res = await handler(lambdaRequest, context); + assertLambdaResponse(res, 200, { + success: true, + triggered: false, + }); + assertNockDone(); + }); }); describe('pull_request_review_comment', () => { diff --git a/src/events/commented.ts b/src/events/commented.ts index eb8d85c..3ea590a 100644 --- a/src/events/commented.ts +++ b/src/events/commented.ts @@ -4,13 +4,14 @@ import { PullRequestReviewCommentEvent, Repository, } from '@octokit/webhooks-types'; -import { isTriggerComment, parseTriggerComment } from '../trigger'; +import { isTriggerComment, parseTriggerComment, hasPreamble } from '../trigger'; import { Logger } from 'pino'; import { Config } from '../config'; import { buildkiteStartBuild } from '../buildkite'; import { isIssueComment, githubGetPullRequestDetails, + githubAddComment, githubUpdateComment, } from '../github'; import type { RestEndpointMethodTypes } from '@octokit/rest'; @@ -48,6 +49,7 @@ export async function commented( config: Config, apis: GithubApis, ): Promise { + const { octokit } = apis; if (eventBody.action === 'deleted') { logger.info('Comment was deleted, nothing to do here'); return { success: true, triggered: false }; @@ -62,15 +64,35 @@ export async function commented( return { success: true, triggered: false }; } if (!isTriggerComment(eventBody.comment.body)) { - logger.info('Not a comment to trigger a build run, nothing to do here'); - return { success: true, triggered: false }; + if (hasPreamble(eventBody.comment.body)) { + const commentData = await githubAddComment( + octokit, + logger, + eventBody.repository, + isIssueComment(currentEventType, eventBody) + ? eventBody.issue.number + : eventBody.pull_request.number, + "Your last comment looked similar to a command but Rocketbot couldn't understand it. Were you trying to [run a build](https://github.com/canva-public/rocketbot/blob/main/docs/getting-started.md#run-a-build)?", + ); + logger.info( + 'Contains preamble but did not qualify as a trigger. Warned the user', + ); + return { + success: true, + triggered: false, + commented: true, + commentUrl: commentData.html_url, + }; + } else { + logger.info('Not a comment to trigger a build run, nothing to do here'); + return { success: true, triggered: false }; + } } const pr = isIssueComment(currentEventType, eventBody) ? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion eventBody.issue.pull_request! // we know it came from a PR, otherwise we'd have exited above : eventBody.pull_request; - const requestedBuildData = parseTriggerComment(eventBody.comment.body); const commentUrl = eventBody.comment.url; const commenter = eventBody.sender.login; @@ -91,7 +113,6 @@ export async function commented( {}, ); - const { octokit } = apis; const [prData, { name: senderName, email: senderEmail }] = await Promise.all< PullRequestContext, UserData diff --git a/src/events/pr_opened.ts b/src/events/pr_opened.ts index fcdf8cc..5d2203b 100644 --- a/src/events/pr_opened.ts +++ b/src/events/pr_opened.ts @@ -102,7 +102,7 @@ ${links[slug]} octokit, logger, eventBody.repository, - eventBody.pull_request, + eventBody.pull_request.number, ` :tada: Almost merged!
diff --git a/src/github.ts b/src/github.ts index f8c918f..547839b 100644 --- a/src/github.ts +++ b/src/github.ts @@ -1,6 +1,5 @@ import type { IssueCommentEvent, - PullRequest, Repository, WebhookEvent, WebhookEventName, @@ -37,21 +36,17 @@ export async function githubAddComment( octokit: Octokit, logger: Logger, repository: Repository, - pullRequest: PullRequest, + issueNumber: number, body: string, ): Promise< RestEndpointMethodTypes['issues']['createComment']['response']['data'] > { - logger.debug( - 'adding comment to %s#%s', - repository.full_name, - pullRequest.number, - ); + logger.debug('adding comment to %s#%s', repository.full_name, issueNumber); return ( await octokit.issues.createComment({ owner: repository.owner.login, repo: repository.name, - issue_number: pullRequest.number, + issue_number: issueNumber, body, }) ).data; diff --git a/src/trigger.ts b/src/trigger.ts index 8a89da5..7dd855a 100644 --- a/src/trigger.ts +++ b/src/trigger.ts @@ -26,6 +26,15 @@ export function isTriggerComment(commentBody: string): boolean { return buildTriggerRegex.test(commentBody); } +/** + * Determines whether a given comment contains the preamble + * @param commentBody + * @return {boolean} + */ +export function hasPreamble(commentBody: string): boolean { + return new RegExp(`^${preamblePattern}`).test(commentBody); +} + /** * Transforms an env variable block into an object *