commit ed9101ddfc2c5cae39bd53ae898aaed706946a4a
parent 96d504731f9544821d8b90bbbdb759fb5e9534db
Author: iostpa <iostpa@iostpa.com>
Date: Sun, 24 May 2026 07:20:47 +0300
feature: add a system for the low priority label (#50)
* Add a system for low priority labels
* v1.3.0
Diffstat:
5 files changed, 122 insertions(+), 19 deletions(-)
diff --git a/.env.example b/.env.example
@@ -4,3 +4,8 @@ PRIVATE_KEY_PATH="private-key.pem"
WEBHOOK_SECRET=""
SENTRY=""
PORT="3000"
+SQL_HOST=""
+SQL_PORT=""
+SQL_USER=""
+SQL_PASSWORD=""
+SQL_DB_NAME=""
diff --git a/bun.lock b/bun.lock
@@ -9,6 +9,7 @@
"@sentry/bun": "^10.53.1",
"dotenv": "^17.4.2",
"fastify": "^5.8.5",
+ "mariadb": "^3.5.2",
"octokit": "^5.0.5",
},
"devDependencies": {
@@ -184,6 +185,8 @@
"@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
+ "@types/geojson": ["@types/geojson@7946.0.16", "", {}, "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg=="],
+
"@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],
"@types/mysql": ["@types/mysql@2.15.27", "", { "dependencies": { "@types/node": "*" } }, ""],
@@ -230,6 +233,8 @@
"deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="],
+ "denque": ["denque@2.1.0", "", {}, "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw=="],
+
"dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="],
"dotenv": ["dotenv@17.4.2", "", {}, "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw=="],
@@ -294,6 +299,8 @@
"globals": ["globals@17.6.0", "", {}, "sha512-sepffkT8stwnIYbsMBpoCHJuJM5l98FUF2AnE07hfvE0m/qp3R586hw4jF4uadbhvg1ooIdzuu7CsfD2jzCaNA=="],
+ "iconv-lite": ["iconv-lite@0.7.2", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw=="],
+
"ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
"import-in-the-middle": ["import-in-the-middle@3.0.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-import-attributes": "^1.9.5", "cjs-module-lexer": "^2.2.0", "module-details-from-path": "^1.0.4" } }, "sha512-OnGy+eYT7wVejH2XWgLRgbmzujhhVIATQH0ztIeRilwHBjTeG3pD+XnH3PKX0r9gJ0BuJmJ68q/oh9qgXnNDQg=="],
@@ -324,6 +331,10 @@
"locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="],
+ "lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
+
+ "mariadb": ["mariadb@3.5.2", "", { "dependencies": { "@types/geojson": "^7946.0.16", "@types/node": ">=18", "denque": "^2.1.0", "iconv-lite": "^0.7.2", "lru-cache": "^10.4.3" } }, "sha512-9rztrI4nouxAY/82a+RlzzZ5ie2vxu2eYclkBvTy1ATXH1B9cnvZ0O71Pzsy/mlfDb5P3HhOg0JzQKkDRhctyA=="],
+
"minimatch": ["minimatch@10.2.4", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg=="],
"module-details-from-path": ["module-details-from-path@1.0.4", "", {}, ""],
@@ -392,6 +403,8 @@
"safe-stable-stringify": ["safe-stable-stringify@2.5.0", "", {}, "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA=="],
+ "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
+
"secure-json-parse": ["secure-json-parse@4.1.0", "", {}, "sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA=="],
"semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
diff --git a/index.js b/index.js
@@ -5,6 +5,7 @@ import middie from '@fastify/middie';
import Fastify from 'fastify';
import { App } from 'octokit';
import { createNodeMiddleware } from '@octokit/webhooks';
+const mariadb = require('mariadb');
// Load environment variables from .env file
dotenv.config();
@@ -31,6 +32,17 @@ Sentry.init({
integrations: [Sentry.bunRuntimeMetricsIntegration()],
});
+// Database
+const pool = mariadb.createPool({
+ user: process.env.SQL_USER,
+ password: process.env.SQL_PASSWORD,
+ host: process.env.SQL_HOST,
+ port: process.env.SQL_PORT,
+ database: process.env.SQL_DB_NAME,
+ ssl: false,
+ connectionLimit: 5
+});
+
// Create an authenticated Octokit client authenticated as a GitHub App
const app = new App({
appId,
@@ -49,6 +61,7 @@ app.octokit.log.debug(`Authenticated as '${data.name}'`);
// https://docs.github.com/en/webhooks/webhook-events-and-payloads#pull_request
app.webhooks.on('pull_request.opened', async ({ octokit, payload }) => {
console.log(`Received a open pull request event for #${payload.pull_request.number} on https://github.com/${payload.repository.full_name}`);
+ let conn;
try {
const labels = await octokit.rest.issues.listLabelsOnIssue({
owner: payload.repository.owner.login,
@@ -77,7 +90,37 @@ app.webhooks.on('pull_request.opened', async ({ octokit, payload }) => {
});
console.log(`Sent a opened message to #${payload.pull_request.number} on https://github.com/${payload.repository.full_name}`);
};
- ;
+ // low priority check
+ conn = await pool.getConnection();
+ let res = await conn.query(`SELECT * FROM LIST WHERE username=(?)`, [payload.pull_request.user.login]);
+ let resJson = JSON.stringify(res);
+ let parsed = JSON.parse(resJson);
+ if (parsed[0].username === payload.pull_request.user.login) {
+ let lowPriority = `
+# Low priority
+
+You're attempting to create a new pull request to bypass the low priority label placed on your previous PR, ${parsed[0].prnumber}. Unfortunately, we've noticed this attempt, and we're applying the label you were trying to escape on this pull request, too.
+
+If you think this is a mistake then please contact [iostpa](https://github.com/iostpa).
+ `;
+ await octokit.request('POST /repos/{owner}/{repo}/issues/{issue_number}/labels', {
+ owner: payload.repository.owner.login,
+ repo: payload.repository.name,
+ issue_number: payload.pull_request.number,
+ labels: [
+ 'status: low priority'
+ ]
+ });
+ await octokit.rest.issues.createComment({
+ owner: payload.repository.owner.login,
+ repo: payload.repository.name,
+ issue_number: payload.pull_request.number,
+ body: lowPriority
+ });
+ console.log(`Auto-added and sent low priority message to #${payload.pull_request.number} on https://github.com/${payload.repository.full_name} because it was found in the database.`);
+ } else if (!res) {
+ return;
+ }
} catch (error) {
Sentry.captureException(error);
fastify.log.error(error);
@@ -86,6 +129,8 @@ app.webhooks.on('pull_request.opened', async ({ octokit, payload }) => {
} else {
console.error(error);
}
+ } finally {
+ if (conn) conn.end();
}
});
@@ -134,16 +179,9 @@ app.webhooks.on('pull_request.labeled', async ({ octokit, payload }) => {
const labelMessages = allMessages.join('\n\n');
let body;
if (!labelMessages.length) {
- body = `
-# Invalid Pull Request
-
-This pull request is invalid. Unfortunately the reviewer didn't specify what is wrong with the pull request.
-
-If you need any help, please create an issue or ask our team in the [Discord server](https://discord.gg/is-a-dev-830872854677422150)
-
-`;
+ body = fs.readFileSync('./message/invalidnolabel.md', 'utf8');
} else {
- body = `
+ body = `
# Invalid Pull Request
This pull request is invalid due to the following reason(s):
@@ -183,14 +221,24 @@ If you need any help, please create an issue or ask our team in the [Discord ser
}
};
} else if (lowpriority === true) {
+ let conn;
try {
- await octokit.rest.issues.createComment({
- owner: payload.repository.owner.login,
- repo: payload.repository.name,
- issue_number: payload.pull_request.number,
- body: lowPriorityMessage
- });
- console.log(`Sent low priority message to ${payload.pull_request.number} from ${payload.repository.name}`);
+ conn = await pool.getConnection();
+ let res = await conn.query(`SELECT * FROM LIST WHERE username=(?)`, [payload.pull_request.user.login]);
+ let resJson = JSON.stringify(res);
+ if (resJson === "[]") {
+ await octokit.rest.issues.createComment({
+ owner: payload.repository.owner.login,
+ repo: payload.repository.name,
+ issue_number: payload.pull_request.number,
+ body: lowPriorityMessage
+ });
+ console.log(`Sent low priority message to #${payload.pull_request.number} from ${payload.repository.name}`);
+ res = await conn.query("INSERT INTO LIST VALUES (?, ?)", [payload.pull_request.user.login, payload.pull_request.number]);
+ console.log(`Logged #${payload.pull_request.number} from ${payload.repository.name} to the low priority database.`);
+ } else {
+ return;
+ }
} catch (error) {
Sentry.captureException(error);
fastify.log.error(error);
@@ -199,6 +247,8 @@ If you need any help, please create an issue or ask our team in the [Discord ser
} else {
console.error(error);
}
+ } finally {
+ if (conn) conn.end();
};
}
});
@@ -237,6 +287,33 @@ app.webhooks.on('pull_request.closed', async ({ octokit, payload }) => {
}
});
+app.webhooks.on('pull_request.unlabeled', async ({ payload }) => {
+ let conn;
+ try {
+ if (payload.label.name === "status: low priority") {
+ conn = await pool.getConnection();
+ let res = await conn.query(`SELECT * FROM LIST WHERE username=(?)`, [payload.pull_request.user.login]);
+ let resJson = JSON.stringify(res);
+ if (resJson !== "[]") {
+ res = await conn.query("DELETE FROM LIST WHERE username=(?)", [payload.pull_request.user.login]);
+ console.log(`Removed #${payload.pull_request.number} from ${payload.repository.name} from the low priority database.`);
+ } else {
+ return;
+ }
+ }
+ } catch (error) {
+ Sentry.captureException(error);
+ fastify.log.error(error);
+ if (error.response) {
+ console.error(`Error! Status: ${error.response.status}. Message: ${error.response.data.message}`);
+ } else {
+ console.error(error);
+ }
+ } finally {
+ if (conn) conn.end();
+ }
+});
+
// Handle errors
app.webhooks.onError((error) => {
Sentry.captureException(error);
@@ -275,4 +352,4 @@ http.createServer(middleware).listen(port, () => {
console.log(`Server is listening for events at: ${localWebhookUrl}`)
console.log('Press Ctrl + C to quit.')
})
-*/
+*/+
\ No newline at end of file
diff --git a/message/invalidnolabel.md b/message/invalidnolabel.md
@@ -0,0 +1,5 @@
+# Invalid Pull Request
+
+This pull request is invalid. Unfortunately the reviewer didn't specify what is wrong with the pull request.
+
+If you need any help, please create an issue or ask our team in the [Discord server](https://discord.gg/is-a-dev-830872854677422150)+
\ No newline at end of file
diff --git a/package.json b/package.json
@@ -1,7 +1,7 @@
{
"name": "reviewbot",
"private": true,
- "version": "1.2.2",
+ "version": "1.3.0",
"type": "module",
"description": "An app to assist in the review process of is-a-dev",
"author": "iostpa",
@@ -20,6 +20,7 @@
"@sentry/bun": "^10.53.1",
"dotenv": "^17.4.2",
"fastify": "^5.8.5",
+ "mariadb": "^3.5.2",
"octokit": "^5.0.5"
}
}