@@ -30,13 +30,184 @@ type GetFileResponse = {
30
30
} ;
31
31
} ;
32
32
33
+
34
+ const getPaths = `
35
+ query getPaths($owner: String!, $repo: String!, $number: Int!, cursor: String = "") {
36
+ repository(name: $repo, owner: $owner) {
37
+ pullRequest(number: $number) {
38
+ id
39
+ files(first: 2, after: $cursor) {
40
+ edges {
41
+ node {
42
+ path
43
+ }
44
+ cursor
45
+ }
46
+ }
47
+ }
48
+ }
49
+ }
50
+ `
51
+
52
+ function checkPathsResponse ( paths : GetPathsResponse ) {
53
+ const edges = paths . repository . pullRequest . files . edges
54
+ const docsChanged = edges . some ( edge => edge . node . path . startsWith ( 'docs/' ) )
55
+ const configChanged = edges . some ( edge => [ "docs.json" , "docs.yaml" ] . includes ( edge . node . path ) )
56
+ return docsChanged || configChanged ;
57
+ }
58
+
59
+ function getLastFileCursor ( getPathsResponse : GetPathsResponse ) {
60
+ const edges = getPathsResponse . repository . pullRequest . files . edges
61
+ return edges [ edges . length - 1 ] . cursor
62
+ }
63
+
64
+
65
+ function checkCommentsResponse ( comments : GetCommentsResponse ) {
66
+ const edges = comments . repository . pullRequest . comments . edges
67
+ const hasCommented = edges . some ( edge => edge . node . author . login === "docs-page" )
68
+ return hasCommented ;
69
+ }
70
+
71
+ function getLastCommentCursor ( getCommentsResponse : GetCommentsResponse ) {
72
+ const edges = getCommentsResponse . repository . pullRequest . comments . edges
73
+ return edges [ edges . length - 1 ] . cursor
74
+ }
75
+
76
+ type GetPathsResponse = {
77
+ repository : {
78
+ pullRequest : {
79
+ files : {
80
+ edges : {
81
+ node : {
82
+ path : string
83
+ }
84
+ cursor : string
85
+ } [ ]
86
+ }
87
+ }
88
+ }
89
+ }
90
+
91
+ const getFirstComments = `
92
+ query getComments($owner: String!, $repo: String!, $number: Int!) {
93
+ repository(name: $repo, owner: $owner) {
94
+ pullRequest(number: $number) {
95
+ comments(first: 100) {
96
+ edges {
97
+ node {
98
+ author {
99
+ login
100
+ }
101
+ }
102
+ cursor
103
+ }
104
+ totalCount
105
+ }
106
+ }
107
+ }
108
+ }
109
+ `
110
+ const getComments = `
111
+ query getComments($owner: String!, $repo: String!, $number: Int!, cursor: String!) {
112
+ repository(name: $repo, owner: $owner) {
113
+ pullRequest(number: $number) {
114
+ comments(first: 100, after: $cursor) {
115
+ edges {
116
+ node {
117
+ author {
118
+ login
119
+ }
120
+ }
121
+ cursor
122
+ }
123
+ }
124
+ }
125
+ }
126
+ }
127
+ `
128
+
129
+ type GetCommentsResponse = {
130
+ repository : {
131
+ pullRequest : {
132
+ comments : {
133
+ edges : {
134
+ node : {
135
+ author : {
136
+ login : string
137
+ }
138
+ }
139
+ cursor : string
140
+ } [ ] ,
141
+ totalCount ?: number
142
+ }
143
+ }
144
+ }
145
+ }
146
+
147
+
33
148
const app = ( app : Probot ) => {
34
- app . on ( 'pull_request.opened' , async context => {
149
+ app . on ( [ 'pull_request.opened' , 'pull_request.synchronize' ] , async context => {
35
150
app . log . info ( context ) ;
36
151
37
- const pull_request = context . payload . pull_request ;
152
+ const { repository, pull_request } = context . payload ;
153
+
154
+ const totalChangedFiles = pull_request . changed_files ;
155
+
156
+ let totalFilesChecked = 0 ;
157
+ let shouldComment = false ;
158
+ let cursor = '' ;
38
159
39
- const { repository } = context . payload ;
160
+ // check files in batches of 100 until we find a docs file or we've checked all files
161
+ while ( totalFilesChecked < totalChangedFiles && ! shouldComment ) {
162
+
163
+ const getPathsResponse = await context
164
+ . octokit
165
+ . graphql < GetPathsResponse > ( getPaths , {
166
+ owner : repository . owner . login ,
167
+ repo : repository . name ,
168
+ number : pull_request . number ,
169
+ cursor
170
+ } ) ;
171
+
172
+ shouldComment = checkPathsResponse ( getPathsResponse ) ;
173
+ cursor = getLastFileCursor ( getPathsResponse ) ;
174
+ }
175
+
176
+ // check to see if we've commented before
177
+
178
+
179
+ // for some reason an empty cursor doesn't work for comments, so we have to obtain the first cursor manually.
180
+ const getFirstCommentsResponse = await context
181
+ . octokit
182
+ . graphql < GetCommentsResponse > ( getFirstComments , {
183
+ owner : repository . owner . login ,
184
+ repo : repository . name ,
185
+ number : pull_request . number ,
186
+ } ) ;
187
+
188
+ let totalComments = getFirstCommentsResponse . repository . pullRequest . comments . totalCount ;
189
+ let totalCommentsChecked = getFirstCommentsResponse . repository . pullRequest . comments . edges . length ;
190
+ let commentCursor = getLastCommentCursor ( getFirstCommentsResponse ) ;
191
+ let hasCommented = checkCommentsResponse ( getFirstCommentsResponse ) ;
192
+
193
+ while ( totalCommentsChecked < totalComments ! && ! hasCommented ) {
194
+ const getCommentsResponse = await context
195
+ . octokit
196
+ . graphql < GetCommentsResponse > ( getComments , {
197
+ owner : repository . owner . login ,
198
+ repo : repository . name ,
199
+ number : pull_request . number ,
200
+ cursor : commentCursor
201
+ } ) ;
202
+ hasCommented = checkCommentsResponse ( getCommentsResponse ) ;
203
+ commentCursor = getLastCommentCursor ( getCommentsResponse ) ;
204
+ }
205
+
206
+ shouldComment = shouldComment && ! hasCommented ;
207
+
208
+ if ( ! shouldComment ) {
209
+ return ;
210
+ }
40
211
41
212
// e.g. org/repo
42
213
const name = repository . full_name . toLowerCase ( ) ;
0 commit comments