-
Notifications
You must be signed in to change notification settings - Fork 45
/
tickethacks.js
252 lines (239 loc) · 11.3 KB
/
tickethacks.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
//
// Hacks for the ticket page.
//
$(function() {
// Don't collapse ticket properties.
$("#modify").parent().removeClass('collapsed');
//
// Link field names to the corresponding sections in the Triaging doc.
//
var linkMap = {
"h_stage": "triage-stages",
"h_ui_ux": "ui-ux",
"h_version": "version",
"h_component": "component",
"h_severity": "severity",
"h_needs_docs": "needs-documentation",
"h_needs_better_patch": "patch-needs-improvement",
"h_cc": "cc",
"h_has_patch": "has-patch",
"h_easy": "easy-pickings",
"h_keywords": "keywords",
"h_needs_tests": "needs-tests"
}
$("table.properties th").each(function(){
var $this = $(this);
var anchor = linkMap[$this.attr("id")];
if (anchor) {
$this.wrapInner(function(){
return "<a href='https://docs.djangoproject.com/en/dev/internals/contributing/triaging-tickets/#" + anchor + "' target='_blank'></a>";
});
}
});
// Show Pull Requests from Github with titles matching any of the following
// patterns: "#<ticket_id> ", "#<ticket_id>,", "#<ticket_id>:", "#<ticket_id>)
var ticket_id = window.location.pathname.split('/')[2];
$.getJSON("https://api.github.com/search/issues?q=repo:django/django+in:title+type:pr+"
+ "%23"+ticket_id+"%20"
+ "+%23"+ticket_id+"%2C"
+ "+%23"+ticket_id+"%3A"
+ "+%23"+ticket_id+"%29",
function(data) {
var links = data.items.map(function(item) {
if (item.number == ticket_id) {
return undefined; // skip this element if PR id == ticket id
}
// open or closed
var pr_state = item.state;
var build_state;
var merged = false;
var url = item.pull_request.html_url;
var link_text = item.number;
if (pr_state === "closed") {
link_text = "<del>"+link_text+"</del>";
}
// Check if our rate limit is exceeded. If it is, just display
// the PRs without additional infos
var core_rate_limit_exceeded = false;
$.ajax({
url: "https://api.github.com/rate_limit",
dataType: 'json',
async: false,
success: function (data, textStatus, xhr) {
// We need to perform a maximum of 3 extra requests to get status infos
if(data.resources.core.remaining < 3) {
core_rate_limit_exceeded = true;
}
}
});
if(!core_rate_limit_exceeded) {
// Get merge state of PR
$.ajax({
url: "https://api.github.com/repos/django/django/pulls/" + item.number + "/merge",
dataType: 'json',
async: false,
success: function (data, textStatus, xhr) {
merged = true;
},
error: function (xhr) {
if (xhr.status === 404) {
merged = false;
}
}
});
if(!merged) {
// Check if the PR was merged manually
$.ajax({
url: "https://api.github.com/repos/django/django/issues/"+ item.number +"/comments",
dataType: 'json',
async: false,
success: function(data) {
$.each(data, function(index, value) {
// Look for "merged/fixed in sha1..."
if(value.body.match(/(merged|fixed) in \b[0-9a-f]{40}\b/i)) {
merged = true;
}
});
}
});
}
if (pr_state === 'open') {
// Get build state of PR if pr_state is open
$.ajax({
url: "https://api.github.com/repos/django/django/pulls/" + item.number,
dataType: 'json',
async: false,
success: function (data) {
$.ajax({
url: data.statuses_url,
dataType: 'json',
async: false,
success: function (data) {
if (data.length > 0) {
build_state = data[0].state;
link_text += " build:" + build_state;
}
}
});
}
});
} else {
// if PR state is closed, display if it was merged or not
if (merged === true) {
link_text += " merged";
} else {
link_text += " unmerged";
}
}
}
return "<a href='" + url + "'>" + link_text + "</a>";
});
var link = '<a href="https://docs.djangoproject.com/en/dev/internals/contributing/writing-code/working-with-git/#publishing-work">How to create a pull request</a>';
if (links.length > 0) {
link = links.join(", ");
}
$("table.properties").append("<tr><th>Pull Requests:</th><td>" + link + "</td><tr>");
});
// Ticket Triage Guidelines: show next steps based on the ticket's status,
// flags, etc.
function get_boolean_ticket_flag(name) {
return $('#h_' + name).next().text().trim() === 'yes';
}
function get_ticket_flag(name) {
return $('#h_' + name).next().text().trim();
}
var stage = get_ticket_flag('stage');
var ticket_status = $('.trac-status').text().trim();
var ticket_type = $('.trac-type').text().trim();
var has_patch = get_boolean_ticket_flag('has_patch');
var patch_needs_improvement = get_boolean_ticket_flag('needs_better_patch');
var needs_docs = get_boolean_ticket_flag('needs_docs');
var needs_tests = get_boolean_ticket_flag('needs_tests');
var next_steps = [];
var include_link_to_pr_msg = (
"include a link to the pull request in the ticket comment when making " +
"that update. The usual format is: <code>[https://github.com/django/django/pull/#### PR]</code>."
);
if (ticket_status == 'closed') {
// TODO (e.g. reopening a wontfix or needsinfo, or what to do in the
// case of a regression caused by the ticket
} else if (stage == 'Unreviewed') {
next_steps.push(
"For bugs: reproduce the bug. If it's a regression, " +
"<a href='https://docs.djangoproject.com/en/dev/internals/contributing/triaging-tickets/#bisecting-a-regression'>" +
"bisect</a> to find the commit where the behavior changed."
);
next_steps.push(
"For new features or cleanups: give a second opinion of the proposal."
);
next_steps.push(
"In either case, mark the Triage Stage as \"Accepted\" if the issue seems valid, " +
"ask for additional clarification from the reporter, or close the ticket."
);
} else if (stage == 'Accepted') {
if (!has_patch) {
next_steps.push(
"<a href='https://docs.djangoproject.com/en/dev/internals/contributing/writing-code/submitting-patches/'>" +
"To provide a patch</a> by sending a pull request. " +
"<a href='https://docs.djangoproject.com/en/dev/internals/contributing/writing-code/submitting-patches/#claiming-tickets'>" +
"Claim the ticket</a> when you start working so that someone else doesn't duplicate effort. " +
"Before sending a pull request, review your work against the <a href='" +
"https://docs.djangoproject.com/en/dev/internals/contributing/writing-code/submitting-patches/#patch-review-checklist'>" +
"patch review checklist</a>. " +
"Check the \"Has patch\" flag on the ticket after sending a pull request and " +
include_link_to_pr_msg
);
} else {
if (needs_tests) {
next_steps.push('To add tests to the patch, then uncheck the "Needs tests" flag on the ticket.');
}
if (needs_docs) {
next_steps.push('To write documentation for the patch, then uncheck "Needs documentation" on the ticket.');
}
if (patch_needs_improvement) {
next_steps.push(
"To improve the patch as described in the pull request review " +
"comments or on this ticket, then uncheck \"Patch needs improvement\"."
);
}
if (!needs_tests && !needs_docs && !patch_needs_improvement) {
next_steps.push(
'For anyone except the patch author to review the patch using the ' +
'<a href="https://docs.djangoproject.com/en/dev/internals/contributing/writing-code/submitting-patches/#patch-review-checklist">' +
'patch review checklist</a> and either ' +
'mark the ticket as "Ready for checkin" if everything looks good, ' +
'or leave comments for improvement and mark the ticket as ' +
'"Patch needs improvement".'
);
} else {
next_steps.push("<p>If creating a new pull request, " + include_link_to_pr_msg);
}
}
} else if (stage == 'Ready for checkin') {
next_steps.push(
'For a Django committer to do a final review of the patch and merge ' +
'it if all looks good.'
);
} else if (stage == 'Someday/Maybe') {
next_steps.push(
'<p>Unknown. The Someday/Maybe triage stage is used ' +
'to keep track of high-level ideas or long term feature requests.</p>' +
'<p>It could be an issue that\'s blocked until a future version of Django ' +
'(if so, Keywords will contain that version number). It could also ' +
'be an enhancement request that we might consider adding someday to the framework ' +
'if an excellent patch is submitted.</p>' +
'<p>If you\'re interested in contributing to the issue, ' +
'raising your ideas on the <a href="http://groups.google.com/group/django-developers">django-developers</a> ' +
'mailing list certainly wouldn\'t hurt.<p>'
);
}
if (next_steps.length) {
$("#ticket").after(
"<div id='ticket-next-steps' class='trac-content'><p>According to the " +
"<a href='https://docs.djangoproject.com/en/dev/internals/contributing/triaging-tickets/#triage-workflow'>" +
"ticket's flags</a>, the next step(s) to move this issue forward are:</p>" +
"<ul><li>" + next_steps.join('</li><li>') + "</li></ul>" +
"</div>"
);
}
});