@opentermsarchive/engine 2.3.0 β 2.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/src/reporter/github.js +103 -124
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opentermsarchive/engine",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.1",
|
|
4
4
|
"description": "Tracks and makes visible changes to the terms of online services",
|
|
5
5
|
"homepage": "https://opentermsarchive.org",
|
|
6
6
|
"bugs": {
|
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
"mongodb": "^4.9.0",
|
|
91
91
|
"morgan": "^1.10.0",
|
|
92
92
|
"node-fetch": "^3.1.0",
|
|
93
|
-
"octokit": "
|
|
93
|
+
"octokit": "2.0.2",
|
|
94
94
|
"pdfjs-dist": "^2.9.359",
|
|
95
95
|
"puppeteer": "^22.8.1",
|
|
96
96
|
"puppeteer-extra": "^3.3.6",
|
package/src/reporter/github.js
CHANGED
|
@@ -16,7 +16,14 @@ export default class GitHub {
|
|
|
16
16
|
constructor(repository) {
|
|
17
17
|
const { version } = require('../../package.json');
|
|
18
18
|
|
|
19
|
-
this.octokit = new Octokit({
|
|
19
|
+
this.octokit = new Octokit({
|
|
20
|
+
auth: process.env.OTA_ENGINE_GITHUB_TOKEN,
|
|
21
|
+
userAgent: `opentermsarchive/${version}`,
|
|
22
|
+
throttle: {
|
|
23
|
+
onRateLimit: () => false, // Do not retry after hitting a rate limit error
|
|
24
|
+
onSecondaryRateLimit: () => false, // Do not retry after hitting a secondary rate limit error
|
|
25
|
+
},
|
|
26
|
+
});
|
|
20
27
|
|
|
21
28
|
const [ owner, repo ] = repository.split('/');
|
|
22
29
|
|
|
@@ -25,173 +32,145 @@ export default class GitHub {
|
|
|
25
32
|
|
|
26
33
|
async initialize() {
|
|
27
34
|
this.MANAGED_LABELS = require('./labels.json');
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
35
|
+
try {
|
|
36
|
+
const existingLabels = await this.getRepositoryLabels();
|
|
37
|
+
const existingLabelsNames = existingLabels.map(label => label.name);
|
|
38
|
+
const missingLabels = this.MANAGED_LABELS.filter(label => !existingLabelsNames.includes(label.name));
|
|
39
|
+
|
|
40
|
+
if (missingLabels.length) {
|
|
41
|
+
logger.info(`Following required labels are not present on the repository: ${missingLabels.map(label => `"${label.name}"`).join(', ')}. Creating themβ¦`);
|
|
42
|
+
|
|
43
|
+
for (const label of missingLabels) {
|
|
44
|
+
await this.createLabel({ /* eslint-disable-line no-await-in-loop */
|
|
45
|
+
name: label.name,
|
|
46
|
+
color: label.color,
|
|
47
|
+
description: `${label.description} ${MANAGED_BY_OTA_MARKER}`,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
42
50
|
}
|
|
51
|
+
} catch (error) {
|
|
52
|
+
logger.error(`Failed to handle repository labels: ${error.message}`);
|
|
43
53
|
}
|
|
44
54
|
}
|
|
45
55
|
|
|
46
56
|
async getRepositoryLabels() {
|
|
47
|
-
|
|
48
|
-
const { data: labels } = await this.octokit.request('GET /repos/{owner}/{repo}/labels', { ...this.commonParams });
|
|
57
|
+
const { data: labels } = await this.octokit.request('GET /repos/{owner}/{repo}/labels', { ...this.commonParams });
|
|
49
58
|
|
|
50
|
-
|
|
51
|
-
} catch (error) {
|
|
52
|
-
logger.error(`π€ Could not get labels: ${error}`);
|
|
53
|
-
}
|
|
59
|
+
return labels;
|
|
54
60
|
}
|
|
55
61
|
|
|
56
62
|
async createLabel({ name, color, description }) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
logger.info(`π€ Created repository label "${name}"`);
|
|
66
|
-
} catch (error) {
|
|
67
|
-
logger.error(`π€ Could not create label "${name}": ${error}`);
|
|
68
|
-
}
|
|
63
|
+
await this.octokit.request('POST /repos/{owner}/{repo}/labels', {
|
|
64
|
+
...this.commonParams,
|
|
65
|
+
name,
|
|
66
|
+
color,
|
|
67
|
+
description,
|
|
68
|
+
});
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
async createIssue({ title, description: body, labels }) {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
logger.info(`π€ Created GitHub issue #${issue.number} "${title}": ${issue.html_url}`);
|
|
81
|
-
|
|
82
|
-
return issue;
|
|
83
|
-
} catch (error) {
|
|
84
|
-
logger.error(`π€ Could not create GitHub issue "${title}": ${error}`);
|
|
85
|
-
}
|
|
72
|
+
const { data: issue } = await this.octokit.request('POST /repos/{owner}/{repo}/issues', {
|
|
73
|
+
...this.commonParams,
|
|
74
|
+
title,
|
|
75
|
+
body,
|
|
76
|
+
labels,
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
return issue;
|
|
86
80
|
}
|
|
87
81
|
|
|
88
82
|
async setIssueLabels({ issue, labels }) {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
logger.info(`π€ Updated labels to GitHub issue #${issue.number}`);
|
|
97
|
-
} catch (error) {
|
|
98
|
-
logger.error(`π€ Could not update GitHub issue #${issue.number} "${issue.title}": ${error}`);
|
|
99
|
-
}
|
|
83
|
+
await this.octokit.request('PUT /repos/{owner}/{repo}/issues/{issue_number}/labels', {
|
|
84
|
+
...this.commonParams,
|
|
85
|
+
issue_number: issue.number,
|
|
86
|
+
labels,
|
|
87
|
+
});
|
|
100
88
|
}
|
|
101
89
|
|
|
102
90
|
async openIssue(issue) {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
logger.info(`π€ Opened GitHub issue #${issue.number}`);
|
|
111
|
-
} catch (error) {
|
|
112
|
-
logger.error(`π€ Could not update GitHub issue #${issue.number} "${issue.title}": ${error}`);
|
|
113
|
-
}
|
|
91
|
+
await this.octokit.request('PATCH /repos/{owner}/{repo}/issues/{issue_number}', {
|
|
92
|
+
...this.commonParams,
|
|
93
|
+
issue_number: issue.number,
|
|
94
|
+
state: GitHub.ISSUE_STATE_OPEN,
|
|
95
|
+
});
|
|
114
96
|
}
|
|
115
97
|
|
|
116
98
|
async closeIssue(issue) {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
logger.info(`π€ Closed GitHub issue #${issue.number}`);
|
|
125
|
-
} catch (error) {
|
|
126
|
-
logger.error(`π€ Could not update GitHub issue #${issue.number} "${issue.title}": ${error}`);
|
|
127
|
-
}
|
|
99
|
+
await this.octokit.request('PATCH /repos/{owner}/{repo}/issues/{issue_number}', {
|
|
100
|
+
...this.commonParams,
|
|
101
|
+
issue_number: issue.number,
|
|
102
|
+
state: GitHub.ISSUE_STATE_CLOSED,
|
|
103
|
+
});
|
|
128
104
|
}
|
|
129
105
|
|
|
130
106
|
async getIssue({ title, ...searchParams }) {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
}, response => response.data);
|
|
107
|
+
const issues = await this.octokit.paginate('GET /repos/{owner}/{repo}/issues', {
|
|
108
|
+
...this.commonParams,
|
|
109
|
+
per_page: 100,
|
|
110
|
+
...searchParams,
|
|
111
|
+
}, response => response.data);
|
|
137
112
|
|
|
138
|
-
|
|
113
|
+
const [issue] = issues.filter(item => item.title === title); // since only one is expected, use the first one
|
|
139
114
|
|
|
140
|
-
|
|
141
|
-
} catch (error) {
|
|
142
|
-
logger.error(`π€ Could not find GitHub issue "${title}": ${error}`);
|
|
143
|
-
}
|
|
115
|
+
return issue;
|
|
144
116
|
}
|
|
145
117
|
|
|
146
118
|
async addCommentToIssue({ issue, comment: body }) {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
});
|
|
119
|
+
const { data: comment } = await this.octokit.request('POST /repos/{owner}/{repo}/issues/{issue_number}/comments', {
|
|
120
|
+
...this.commonParams,
|
|
121
|
+
issue_number: issue.number,
|
|
122
|
+
body,
|
|
123
|
+
});
|
|
153
124
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
return comment;
|
|
157
|
-
} catch (error) {
|
|
158
|
-
logger.error(`π€ Could not add comment to GitHub issue #${issue.number} "${issue.title}": ${error}`);
|
|
159
|
-
}
|
|
125
|
+
return comment;
|
|
160
126
|
}
|
|
161
127
|
|
|
162
128
|
async closeIssueWithCommentIfExists({ title, comment }) {
|
|
163
|
-
|
|
129
|
+
try {
|
|
130
|
+
const openedIssue = await this.getIssue({ title, state: GitHub.ISSUE_STATE_OPEN });
|
|
164
131
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
132
|
+
if (!openedIssue) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
168
135
|
|
|
169
|
-
|
|
136
|
+
await this.addCommentToIssue({ issue: openedIssue, comment });
|
|
137
|
+
await this.closeIssue(openedIssue);
|
|
170
138
|
|
|
171
|
-
|
|
139
|
+
return logger.info(`Closed issue #${openedIssue.number}: ${openedIssue.html_url}`);
|
|
140
|
+
} catch (error) {
|
|
141
|
+
logger.error(`Failed to update issue "${title}": ${error.message}`);
|
|
142
|
+
}
|
|
172
143
|
}
|
|
173
144
|
|
|
174
145
|
async createOrUpdateIssue({ title, description, label }) {
|
|
175
|
-
|
|
146
|
+
try {
|
|
147
|
+
const issue = await this.getIssue({ title, state: GitHub.ISSUE_STATE_ALL });
|
|
176
148
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
}
|
|
149
|
+
if (!issue) {
|
|
150
|
+
const createdIssue = await this.createIssue({ title, description, labels: [label] });
|
|
180
151
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
}
|
|
152
|
+
return logger.info(`Created issue #${createdIssue.number} "${title}": ${createdIssue.html_url}`);
|
|
153
|
+
}
|
|
184
154
|
|
|
185
|
-
|
|
186
|
-
|
|
155
|
+
if (issue.state == GitHub.ISSUE_STATE_CLOSED) {
|
|
156
|
+
await this.openIssue(issue);
|
|
157
|
+
logger.info(`Reopened issue #${issue.number}: ${issue.html_url}`);
|
|
158
|
+
}
|
|
187
159
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
160
|
+
const managedLabelsNames = this.MANAGED_LABELS.map(label => label.name);
|
|
161
|
+
const [managedLabel] = issue.labels.filter(label => managedLabelsNames.includes(label.name)); // it is assumed that only one specific reason for failure is possible at a time, making managed labels mutually exclusive
|
|
162
|
+
|
|
163
|
+
if (managedLabel?.name == label) { // if the label is already assigned to the issue, the error is redundant with the one already reported and no further action is necessary
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
191
166
|
|
|
192
|
-
|
|
167
|
+
const labelsNotManagedToKeep = issue.labels.map(label => label.name).filter(label => !managedLabelsNames.includes(label));
|
|
193
168
|
|
|
194
|
-
|
|
195
|
-
|
|
169
|
+
await this.setIssueLabels({ issue, labels: [ label, ...labelsNotManagedToKeep ] });
|
|
170
|
+
await this.addCommentToIssue({ issue, comment: description });
|
|
171
|
+
logger.info(`Updated issue #${issue.number}: ${issue.html_url}`);
|
|
172
|
+
} catch (error) {
|
|
173
|
+
logger.error(`Failed to update issue "${title}": ${error.message}`);
|
|
174
|
+
}
|
|
196
175
|
}
|
|
197
176
|
}
|