File size: 5,460 Bytes
bf48b89 | 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 | import remarkParse from 'remark-parse';
import { unified } from 'unified';
// @TODO maybe we could use label or some other better ways to distinguish bug/feature issues
const matchTitle = ['路由地址', 'Routes'];
const maintainerURL = 'https://raw.githubusercontent.com/DIYgod/RSSHub/gh-pages/build/maintainers.json';
const successTag = 'bug ping: pinged';
const parseFailTag = 'bug ping: parsing failed';
const failTag = 'bug ping: not found';
const deprecatedRoute = 'route: deprecated';
const route = 'route';
// DnD (do-not-disturb) usernames, add yours here to avoid being notified
// eslint-disable-next-line unicorn/no-useless-collection-argument
const dndUsernames = new Set([]);
async function parseBodyRoutes(body, core) {
const ast = await unified().use(remarkParse).parse(body);
// Is this a bug report?
const title = ast.children[0].children[0].value.trim();
core.debug(`title: ${title}`);
if (!matchTitle.some((ele) => ele.localeCompare(title) === 0)) {
return null;
}
let routes = ast.children[1].value.trim();
core.debug(`routes: ${JSON.stringify(routes)}`);
if (routes.localeCompare('NOROUTE') === 0) {
return null;
}
if (routes) {
routes = routes.split(/\r?\n/).filter(Boolean);
const dedup = [...new Set(routes)];
if (dedup.length !== routes.length) {
core.warning('Duplication detected.');
}
core.debug(dedup);
return dedup;
}
throw new Error('unable to parse the issue body: route does not exist');
}
async function getMaintainersByRoutes(routes, core) {
const response = await fetch(maintainerURL);
const maintainers = await response.json();
return routes.map((e) => {
const m = maintainers[e];
if (m === undefined) {
core.warning(`Route ${e} not found`);
}
return m;
});
}
export default async function callMaintainer({ github, context, core }) {
const body = context.payload.issue.body;
const issueFacts = {
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
};
const addLabels = (labels) =>
github.rest.issues
.addLabels({
...issueFacts,
labels,
})
.catch((error) => {
core.warning(error);
});
const updateIssueState = (state) =>
github.rest.issues
.update({
...issueFacts,
state,
})
.catch((error) => {
core.warning(error);
});
if (context.payload.issue.state === 'closed') {
await updateIssueState('open');
}
const routes = await parseBodyRoutes(body, core).catch((error) => {
core.warning(error);
});
if (routes === null) {
return; // Not a bug report, or NOROUTE
}
if (routes === undefined) {
await addLabels([parseFailTag]);
return;
}
const maintainers = await getMaintainersByRoutes(routes, core);
let successCount = 0;
let emptyCount = 0;
let failedCount = 0;
let comments = '##### Searching for maintainers: \n\n';
for (const [i, route] of routes.entries()) {
const main = maintainers[i];
if (main === undefined) {
comments += `- \`${route}\`: **Route not found**\n`;
failedCount += 1;
continue;
}
if (main.length === 0) {
comments += `- \`${route}\`: No maintainer listed, possibly a v1 or misconfigured route\n`;
emptyCount += 1;
continue;
}
if (main.length > 0) {
const pingStr = main
.map((e) => {
if (dndUsernames.has(e)) {
return `\`@${e}\``; // Wrap in an inline code block to make sure no mention will be sent
}
return `@${e}`;
})
.join(' ');
comments += `- \`${route}\`: ${pingStr}\n`;
successCount += 1;
}
}
const labels = [''];
if (failedCount > 0) {
labels.push(failTag);
} else {
labels.push(successTag);
}
if (emptyCount > 0) {
labels.push(deprecatedRoute);
}
if (successCount > 0) {
labels.push(route);
}
// Write labels (status, affected route count)
await addLabels(labels);
// Reply to the issue and notify the maintainers (if any)
await github.rest.issues
.createComment({
...issueFacts,
body: `${comments}
> To maintainers: if you are not willing to be disturbed, list your username in \`scripts/workflow/test-issue/call-maintainer.js\`. In this way, your username will be wrapped in an inline code block when tagged so you will not be notified.
If all routes can not be found, the issue will be closed automatically. Please use \`NOROUTE\` for a route-irrelevant issue or leave a comment if it is a mistake.
如果所有路由都无法匹配,issue 将会被自动关闭。如果 issue 和路由无关,请使用 \`NOROUTE\` 关键词,或者留下评论。我们会重新审核。
`,
})
.catch((error) => {
core.warning(error);
});
if (failedCount && emptyCount === 0 && successCount === 0) {
await updateIssueState('closed');
}
}
|