@hachej/boring-feedback 0.4.8 → 0.4.10
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/dist/tickets/sinks.js +17 -1
- package/package.json +4 -4
package/dist/tickets/sinks.js
CHANGED
|
@@ -1,8 +1,22 @@
|
|
|
1
1
|
export const GITHUB_API = 'https://api.github.com';
|
|
2
2
|
const REPO = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/;
|
|
3
|
+
const isRepo = (repo) => REPO.test(repo) && !repo.split('/').some(part => part === '.' || part === '..');
|
|
4
|
+
/** The token is sent only over https; plain http is for a loopback test server. */
|
|
5
|
+
function secureApi(apiUrl) {
|
|
6
|
+
let url;
|
|
7
|
+
try {
|
|
8
|
+
url = new URL(apiUrl);
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
if (url.username || url.password)
|
|
14
|
+
return false;
|
|
15
|
+
return url.protocol === 'https:' || (url.protocol === 'http:' && (url.hostname === 'localhost' || url.hostname === '[::1]' || /^127(?:\.\d{1,3}){3}$/.test(url.hostname)));
|
|
16
|
+
}
|
|
3
17
|
/** The repository a project's tickets go to: the one with role `app`, else the first; only `owner/name` entries count. */
|
|
4
18
|
export function ticketRepoOf(project) {
|
|
5
|
-
const repos = project.repos.filter(item =>
|
|
19
|
+
const repos = project.repos.filter(item => isRepo(item.repo));
|
|
6
20
|
return (repos.find(item => item.role === 'app') ?? repos[0])?.repo;
|
|
7
21
|
}
|
|
8
22
|
const REFUSALS = {
|
|
@@ -41,6 +55,8 @@ export function githubSink(options) {
|
|
|
41
55
|
const repo = ticketRepoOf(context.project);
|
|
42
56
|
if (!repo)
|
|
43
57
|
return { refused: `The project "${context.project.name}" names no GitHub repository.` };
|
|
58
|
+
if (!secureApi(api))
|
|
59
|
+
return { refused: 'The GitHub API address must be https (http only for localhost); the token was not sent.' };
|
|
44
60
|
const labels = [...new Set([...ticket.labels, ...extra])];
|
|
45
61
|
const body = `${ticket.body}\n\n<!-- boring-ticket: ${ticket.id} -->\n`;
|
|
46
62
|
const signal = context.signal ? AbortSignal.any([context.signal, AbortSignal.timeout(timeoutMs)]) : AbortSignal.timeout(timeoutMs);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hachej/boring-feedback",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.10",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
@@ -52,9 +52,9 @@
|
|
|
52
52
|
}
|
|
53
53
|
},
|
|
54
54
|
"peerDependencies": {
|
|
55
|
-
"@hachej/boring-ui-kit": "^0.4.
|
|
56
|
-
"@hachej/boring-files": "^0.4.
|
|
57
|
-
"@hachej/boring-agent": "^0.4.
|
|
55
|
+
"@hachej/boring-ui-kit": "^0.4.10",
|
|
56
|
+
"@hachej/boring-files": "^0.4.10",
|
|
57
|
+
"@hachej/boring-agent": "^0.4.10",
|
|
58
58
|
"@earendil-works/pi-durable": "~1.2.0",
|
|
59
59
|
"@earendil-works/pi-ai": "~1.2.0",
|
|
60
60
|
"@earendil-works/chord": "~1.2.0",
|