diff --git a/.eslintrc.json b/.eslintrc.json index bc17e12b..bc144bb6 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,23 +1,33 @@ { - "extends": ["eslint:recommended"], + "extends": [ + "eslint:recommended" + ], "parserOptions": { - "ecmaVersion": 2018, + "ecmaVersion": 2022, "sourceType": "module" }, "env": { "browser": true, "node": true, - "es6": true + "es2022": true }, "globals": { "App": true }, - "ignorePatterns": ["dist/*", "frontend/dist/*"], + "ignorePatterns": [ + "dist/*", + "frontend/dist/*" + ], "overrides": [ { - "files": ["**/*.ts", "**/*.tsx"], + "files": [ + "**/*.ts", + "**/*.tsx" + ], "parser": "@typescript-eslint/parser", - "plugins": ["@typescript-eslint"], + "plugins": [ + "@typescript-eslint" + ], "extends": [ "eslint:recommended", "plugin:react/recommended", @@ -49,4 +59,4 @@ "version": "detect" } } -} +} \ No newline at end of file diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 96c8885f..91a4b78a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,7 +13,7 @@ jobs: - name: Setup node uses: actions/setup-node@v3 with: - node-version: "16" + node-version: "18" cache: npm - run: npm install diff --git a/Dockerfile b/Dockerfile index cf558b6f..ee916ff4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:16-alpine +FROM node:18-alpine RUN mkdir -p /opt/pulldasher WORKDIR /opt/pulldasher diff --git a/app.js b/app.js index fab870b7..0c79e298 100644 --- a/app.js +++ b/app.js @@ -1,23 +1,31 @@ -var config = require("./lib/config-loader"), - express = require("express"), - bodyParser = require("body-parser"), - expressSession = require("express-session"), - authManager = require("./lib/authentication"), - passport = authManager.passport, - socketAuthenticator = require("./lib/socket-auth"), - refresh = require("./lib/refresh"), - pullManager = require("./lib/pull-manager"), - dbManager = require("./lib/db-manager"), - pullQueue = require("./lib/pull-queue"), - mainController = require("./controllers/main"), - hooksController = require("./controllers/githubHooks"), - reqLogger = require("./lib/debug")("pulldasher:server:request"), - debug = require("./lib/debug")("pulldasher"); +import config from "./lib/config-loader.js"; +import express from "express"; +import bodyParser from "body-parser"; +import expressSession from "express-session"; +import authManager from "./lib/authentication.js"; +import socketAuthenticator from "./lib/socket-auth.js"; +import refresh from "./lib/refresh.js"; +import pullManager from "./lib/pull-manager.js"; +import dbManager from "./lib/db-manager.js"; +import pullQueue from "./lib/pull-queue.js"; +import mainController from "./controllers/main.js"; +import hooksController from "./controllers/githubHooks.js"; +import Debug from "./lib/debug.js"; +import { createServer } from "http"; +import { Server } from "socket.io"; +import { fileURLToPath } from "url"; +import { dirname } from "path"; -var app = express(); -var httpServer = require("http").createServer(app); +const reqLogger = Debug("pulldasher:server:request"); +const debug = Debug("pulldasher"); + +const app = express(); +const httpServer = createServer(app); const maxPostSize = 1024 * 1024; +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + app.set("view engine", "html"); /** @@ -33,8 +41,8 @@ app.use( saveUninitialized: false, }) ); -app.use(passport.initialize()); -app.use(passport.session()); +app.use(authManager.passport.initialize()); +app.use(authManager.passport.session()); app.use(function (req, res, next) { reqLogger("%s %s", req.method, req.url); @@ -73,7 +81,6 @@ dbManager.closeStalePulls(); //==================================================== // Socket.IO -const { Server } = require("socket.io"); const io = new Server(httpServer); io.on("connection", function (socket) { var unauthenticated_timeout = diff --git a/bin/migrate b/bin/migrate index bc6e2da1..a925d6d8 100755 --- a/bin/migrate +++ b/bin/migrate @@ -1,10 +1,10 @@ #!/usr/bin/env node -var config = require('../lib/config-loader'); -var mysql = require('mysql2'), - fs = require('fs'); +import { createConnection } from 'mysql2'; +import { readFileSync } from 'fs/promises'; +import config from '../lib/config-loader.js'; -var db = mysql.createConnection({ +const db = createConnection({ host: config.mysql.host, database: config.mysql.db, user: config.mysql.user, @@ -15,23 +15,19 @@ var db = mysql.createConnection({ console.log("Running this script will initalize your database for pulldasher."); console.log("It will not drop any existing tables."); -fs.readFile('migrations/schema.sql', function(err, data) { +const data = readFileSync('migrations/schema.sql'); + +db.query(data.toString(), function (err) { + // If the connection fails, return a failure code so that entrypoint.sh + // will retry this script. if (err) { - throw err; + console.log(err); + process.exit(1); } - db.query(data.toString(), function(err, res, fields) { - // If the connection fails, return a failure code so that entrypoint.sh - // will retry this script. + db.end(function (err) { if (err) { - console.log(err); - process.exit(1); + throw err; } - - db.end(function(err) { - if (err) { - throw err; - } - }); }); }); diff --git a/bin/pulldasher b/bin/pulldasher index 13d2dc33..b6b9def6 100755 --- a/bin/pulldasher +++ b/bin/pulldasher @@ -1,26 +1,26 @@ #!/usr/bin/env node -var fs = require('fs'); -var config = require('../lib/config-loader'); -var debug = require('../lib/debug')('pulldasher:bin'); +import { writeFileSync, unlinkSync } from 'fs'; +import config from '../lib/config-loader.js'; +import debug from '../lib/debug.js'; // Save the pid to a file if requested (for an init script) if (config.pidFile) { - fs.writeFileSync(config.pidFile, '' + process.pid); - process.on('exit', function() { - var m = "\nExiting..."; + writeFileSync(config.pidFile, '' + process.pid); + process.on('exit', function () { + const m = "\nExiting..."; debug(m); console.warn(m); - fs.unlinkSync(config.pidFile); + unlinkSync(config.pidFile); }); // Without these, the onExit handler above is never called. - process.on('SIGINT', exitBad); + process.on('SIGINT', exitBad); process.on('SIGTERM', exitBad); - process.on('SIGHUP', exitBad); + process.on('SIGHUP', exitBad); function exitBad() { process.exit(1); } } -require(__dirname + "/../app.js"); +import('../app.js'); diff --git a/bin/refresh-all-issues b/bin/refresh-all-issues index eeefb12e..6254fbc2 100755 --- a/bin/refresh-all-issues +++ b/bin/refresh-all-issues @@ -1,10 +1,11 @@ #!/usr/bin/env node -require('../lib/debug').default('pulldasher:refresh*'); +import { default as debugInit } from '../lib/debug.js'; +import refresh from '../lib/refresh.js'; +import db from '../lib/db.js'; -var refresh = require('../lib/refresh'); -var db = require('../lib/db'); +debugInit('pulldasher:refresh*'); refresh.allIssues() -.done(function() { - db.end(); -}); + .done(function () { + db.end(); + }); diff --git a/bin/refresh-all-pulls b/bin/refresh-all-pulls index 33fd6cb7..5c3cb234 100755 --- a/bin/refresh-all-pulls +++ b/bin/refresh-all-pulls @@ -1,10 +1,11 @@ #!/usr/bin/env node -require('../lib/debug').default('pulldasher:refresh*'); +import { default as debugInit } from '../lib/debug.js'; +import refresh from '../lib/refresh.js'; +import db from '../lib/db.js'; -var refresh = require('../lib/refresh'); -var db = require('../lib/db'); +debugInit('pulldasher:refresh*'); refresh.allPulls() -.done(function() { - db.end(); -}); + .done(function () { + db.end(); + }); diff --git a/bin/refresh-issue b/bin/refresh-issue index b2c6dfea..74b4018d 100755 --- a/bin/refresh-issue +++ b/bin/refresh-issue @@ -1,10 +1,12 @@ #!/usr/bin/env node -require('../lib/debug').default('pulldasher:refresh*'); +import { default as debugInit } from '../lib/debug.js'; +import refresh from '../lib/refresh.js'; +import db from '../lib/db.js'; -var refresh = require('../lib/refresh'); -var db = require('../lib/db'); -var repo = process.argv[2]; -var number = process.argv[3]; +debugInit('pulldasher:refresh*'); + +const repo = process.argv[2]; +const number = process.argv[3]; if ("" + parseInt(number, 10) !== number) { console.error("%s is not a number", number) @@ -13,6 +15,6 @@ if ("" + parseInt(number, 10) !== number) { } refresh.issue(repo, number) -.done(function() { - db.end(); -}); + .done(function () { + db.end(); + }); diff --git a/bin/refresh-open-issues b/bin/refresh-open-issues index 98d8e6ac..c8a77acd 100755 --- a/bin/refresh-open-issues +++ b/bin/refresh-open-issues @@ -1,10 +1,11 @@ #!/usr/bin/env node -require('../lib/debug').default('pulldasher:refresh*'); +import { default as debugInit } from '../lib/debug.js'; +import refresh from '../lib/refresh.js'; +import db from '../lib/db.js'; -var refresh = require('../lib/refresh'); -var db = require('../lib/db'); +debugInit('pulldasher:refresh*'); refresh.openIssues() -.done(function() { - db.end(); -}); + .done(function () { + db.end(); + }); diff --git a/bin/refresh-open-pulls b/bin/refresh-open-pulls index 59c4d54c..5ffb1d9d 100755 --- a/bin/refresh-open-pulls +++ b/bin/refresh-open-pulls @@ -1,10 +1,11 @@ #!/usr/bin/env node -require('../lib/debug').default('pulldasher:refresh*'); +import { default as debugInit } from '../lib/debug.js'; +import refresh from '../lib/refresh.js'; +import db from '../lib/db.js'; -var refresh = require('../lib/refresh'); -var db = require('../lib/db'); +debugInit('pulldasher:refresh*'); refresh.openPulls() -.then(function() { - db.end(); -}); + .done(function () { + db.end(); + }); diff --git a/bin/refresh-pull b/bin/refresh-pull index 98cc7139..dc38cbb2 100755 --- a/bin/refresh-pull +++ b/bin/refresh-pull @@ -1,10 +1,12 @@ #!/usr/bin/env node -require('../lib/debug').default('pulldasher:refresh*'); +import { default as debugInit } from '../lib/debug.js'; +import refresh from '../lib/refresh.js'; +import db from '../lib/db.js'; -var refresh = require('../lib/refresh'); -var db = require('../lib/db'); -var repo = process.argv[2]; -var number = process.argv[3]; +debugInit('pulldasher:refresh*'); + +const repo = process.argv[2]; +const number = process.argv[3]; if ("" + parseInt(number, 10) !== number) { console.error("%s is not a number", number) @@ -13,6 +15,6 @@ if ("" + parseInt(number, 10) !== number) { } refresh.pull(repo, number) -.done(function() { - db.end(); -}); + .done(function () { + db.end(); + }); diff --git a/controllers/githubHooks.js b/controllers/githubHooks.js index 4434f752..0b63a916 100644 --- a/controllers/githubHooks.js +++ b/controllers/githubHooks.js @@ -1,19 +1,19 @@ -var config = require("../lib/config-loader"), - Promise = require("bluebird"), - debug = require("../lib/debug")("pulldasher:githubHooks"), - Pull = require("../models/pull"), - Signature = require("../models/signature"), - Issue = require("../models/issue"), - Comment = require("../models/comment"), - Review = require("../models/review"), - Status = require("../models/status"), - Label = require("../models/label"), - refresh = require("../lib/refresh"), - getLogin = require("../lib/get-user-login"), - utils = require("../lib/utils"), - dbManager = require("../lib/db-manager"); +import config from "../lib/config-loader.js"; +import Promise from "bluebird"; +import debug from "../lib/debug.js"; +import Pull from "../models/pull.js"; +import Signature from "../models/signature.js"; +import Issue from "../models/issue.js"; +import Comment from "../models/comment.js"; +import Review from "../models/review.js"; +import Status from "../models/status.js"; +import Label from "../models/label.js"; +import refresh from "../lib/refresh.js"; +import getLogin from "../lib/get-user-login.js"; +import utils from "../lib/utils.js"; +import dbManager from "../lib/db-manager.js"; -var HooksController = { +const HooksController = { main: function (req, res) { // Variable for promise that will resolve when the hook is known to have // succeeded or failed. @@ -300,4 +300,4 @@ function refreshPullOrIssue(responseBody) { } } -module.exports = HooksController; +export default HooksController; diff --git a/controllers/main.js b/controllers/main.js index 893b3d61..1586ff8f 100644 --- a/controllers/main.js +++ b/controllers/main.js @@ -1,12 +1,9 @@ -var socketAuthenticator = require("../lib/socket-auth"); -var socketio = require("../package").dependencies["socket.io"]; -var config = require("../lib/config-loader"); +import socketAuthenticator from "../lib/socket-auth.js"; +import config from "../lib/config-loader.js"; +import { createRequire } from "module"; -module.exports = { - getToken: function (req, res) { - res.json(connectionDetails(req)); - }, -}; +const require = createRequire(import.meta.url); +const socketio = require("../package.json").dependencies["socket.io"]; function connectionDetails(req) { return { @@ -17,3 +14,10 @@ function connectionDetails(req) { debugTools: config.debug, }; } + +export default { + getToken: function (req, res) { + res.json(connectionDetails(req)); + }, +}; + diff --git a/frontend/webpack-define-read-file.js b/frontend/webpack-define-read-file.js index b8b546e7..78cab314 100644 --- a/frontend/webpack-define-read-file.js +++ b/frontend/webpack-define-read-file.js @@ -1,13 +1,13 @@ -const webpack = require("webpack"); -const fs = require("fs"); +import webpack from "webpack"; +import fs from "fs"; /** * Returns an object to be used as a value in the config of * webpack.DefinePlugin. It reads a local file and returns the contents. * It also triggers a webpack rebuild if that file changes. */ -module.exports = function (dummyPullsPath) { +export default function (dummyPullsPath) { return webpack.DefinePlugin.runtimeValue(() => { return fs.readFileSync(dummyPullsPath, { encoding: "utf8" }); }, [dummyPullsPath]); -}; +} diff --git a/frontend/webpack.dev.config.js b/frontend/webpack.dev.config.js index 3a1c8eaa..9728fa60 100644 --- a/frontend/webpack.dev.config.js +++ b/frontend/webpack.dev.config.js @@ -1,15 +1,19 @@ -const webpack = require("webpack"); -const path = require("path"); -const HtmlWebpackPlugin = require("html-webpack-plugin"); -const definePluginReadFile = require("./webpack-define-read-file"); -const ESLintPlugin = require("eslint-webpack-plugin"); +import webpack from "webpack"; +import path from "path"; +import HtmlWebpackPlugin from "html-webpack-plugin"; +import definePluginReadFile from "./webpack-define-read-file.js"; +import ESLintPlugin from "eslint-webpack-plugin"; +import { fileURLToPath } from "url"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); const relative = (pathPart) => path.resolve(__dirname, pathPart); const dummyPullsPath = process.env.DUMMY_PULLS && path.resolve(process.env.DUMMY_PULLS); const dummyUser = process.env.DUMMY_USER; -module.exports = { +export default { node: false, module: { rules: [ diff --git a/frontend/webpack.prod.config.js b/frontend/webpack.prod.config.js index 0ad42dca..24f309b9 100644 --- a/frontend/webpack.prod.config.js +++ b/frontend/webpack.prod.config.js @@ -1,4 +1,4 @@ -const dev = require("./webpack.dev.config.js"); +import dev from "./webpack.dev.config.js"; dev.mode = "production"; dev.devtool = "source-map"; -module.exports = dev; +export default dev; diff --git a/lib/authentication.js b/lib/authentication.js index a21d586b..24812565 100644 --- a/lib/authentication.js +++ b/lib/authentication.js @@ -1,8 +1,10 @@ -var config = require("./config-loader"), - debug = require("./debug")("pulldasher:authentication"), - github = require("./git-manager").github, - passport = require("passport"), - GitHubStrategy = require("passport-github2").Strategy; +import config from "./config-loader.js"; +import debug from "./debug.js"; +import gitManager from "./git-manager.js"; +import passport from "passport"; +import { Strategy as GitHubStrategy } from "passport-github2"; + +const authDebug = debug("pulldasher:authentication"); const FAKE_USER = process.env.MOCK_AUTH_AS_USER; @@ -26,39 +28,57 @@ if (!FAKE_USER) { scope: null, }, function (accessToken, refreshToken, profile, done) { - debug("Authenticating user: " + profile.username); + authDebug("Authenticating user: " + profile.username); return done(null, profile); } ) ); } else { - debug("Using dummy authentication, pretending to be: " + FAKE_USER); + authDebug("Using dummy authentication, pretending to be: " + FAKE_USER); +} + +let checkOrgMembershipRequirements; + +if (config.github.requireTeam) { + checkOrgMembershipRequirements = function (options) { + options.team_slug = config.github.requireTeam; + return gitManager.github.teams.getMembershipForUserInOrg(options); + }; +} else { + checkOrgMembershipRequirements = gitManager.github.orgs.checkMembershipForUser; +} + +function confirmOrgMembership(user) { + return checkOrgMembershipRequirements({ + org: config.github.requireOrg, + username: user.username, + }); } -module.exports = { - passport: passport, +export default { + passport, setupRoutes: function (app) { app.get("/auth/github", passport.authenticate("github")); app.get("/auth/github/callback", function (req, res, next) { passport.authenticate("github", function (err, user) { if (err) { - debug("Error: " + err); + authDebug("Error: " + err); return next(err); } if (user === undefined) { - debug("Bad user"); + authDebug("Bad user"); return next("Bad user"); } - debug("Authenticated with github: " + user.username); + authDebug("Authenticated with github: " + user.username); let afterMembershipValidation; // If the config requires org membership, check that the // user belongs to that org. Otherwise just log in. if (config.github.requireOrg) { afterMembershipValidation = confirmOrgMembership(user).then(() => - debug("Authenticated with org: " + user.username) + authDebug("Authenticated with org: " + user.username) ); } else { afterMembershipValidation = Promise.resolve(); @@ -67,7 +87,7 @@ module.exports = { afterMembershipValidation .then(() => { req.logIn(user, function () { - debug("Got login from " + user.username); + authDebug("Got login from " + user.username); // Redirect user to original URL. Fallback to '/' if DNE. const redirectUrl = req.session.auth_redirect; @@ -100,21 +120,3 @@ module.exports = { app.get("/token", auth); }, }; - -let checkOrgMembershipRequirements; - -if (config.github.requireTeam) { - checkOrgMembershipRequirements = function (options) { - options.team_slug = config.github.requireTeam; - return github.teams.getMembershipForUserInOrg(options); - }; -} else { - checkOrgMembershipRequirements = github.orgs.checkMembershipForUser; -} - -function confirmOrgMembership(user) { - return checkOrgMembershipRequirements({ - org: config.github.requireOrg, - username: user.username, - }); -} diff --git a/lib/config-loader.js b/lib/config-loader.js index 93fc1445..3fd8746c 100644 --- a/lib/config-loader.js +++ b/lib/config-loader.js @@ -1,6 +1,7 @@ -var configPath = process.env.CONFIG_PATH || "../config"; -const config = require(configPath); -module.exports = config; +const configPath = process.env.CONFIG_PATH || "../config.js"; +const { default: config } = await import(configPath); + +export default config; config.repos = config.repos.map(normalizeRepo); diff --git a/lib/db-manager.js b/lib/db-manager.js index 0be56fc9..eac702ad 100644 --- a/lib/db-manager.js +++ b/lib/db-manager.js @@ -1,23 +1,25 @@ -var _ = require("underscore"), - debug = require("./debug")("pulldasher:db-manager"), - Promise = require("bluebird"), - db = require("../lib/db"), - DBIssue = require("../models/db_issue"), - DBStatus = require("../models/db_status"), - DBSignature = require("../models/db_signature"), - DBComment = require("../models/db_comment"), - DBReview = require("../models/db_review"), - DBLabel = require("../models/db_label"), - Pull = require("../models/pull"), - Issue = require("../models/issue"), - Status = require("../models/status"), - Signature = require("../models/signature"), - Comment = require("../models/comment"), - Review = require("../models/review"), - Label = require("../models/label"), - queue = require("../lib/pull-queue"); - -var dbManager = (module.exports = { +import _ from "underscore"; +import debug from "./debug.js"; +import Promise from "bluebird"; +import db from "../lib/db.js"; +import DBIssue from "../models/db_issue.js"; +import DBStatus from "../models/db_status.js"; +import DBSignature from "../models/db_signature.js"; +import DBComment from "../models/db_comment.js"; +import DBReview from "../models/db_review.js"; +import DBLabel from "../models/db_label.js"; +import Pull from "../models/pull.js"; +import Issue from "../models/issue.js"; +import Status from "../models/status.js"; +import Signature from "../models/signature.js"; +import Comment from "../models/comment.js"; +import Review from "../models/review.js"; +import Label from "../models/label.js"; +import queue from "../lib/pull-queue.js"; + +const dbDebug = debug("pulldasher:db-manager"); + +const dbManager = { /** * Takes a Pull object and returns a promise that resolves when the db and * client have been updated with the new pull data. @@ -88,7 +90,7 @@ var dbManager = (module.exports = { * has been updated with the new issue data. */ updateIssue: function (updatedIssue) { - debug("Calling `updateIssue` for issue #%s", updatedIssue.number); + dbDebug("Calling `updateIssue` for issue #%s", updatedIssue.number); var dbIssue = new DBIssue(updatedIssue); return dbIssue.save(); }, @@ -119,7 +121,7 @@ var dbManager = (module.exports = { */ updateCommitStatus: function (status) { const { sha, repo, context } = status.data; - debug( + dbDebug( "Calling `updateCommitStatus` for commit %s in repo %s and context %s", sha, repo, @@ -134,7 +136,7 @@ var dbManager = (module.exports = { // `pullNumber` will be null if we are updating the build status of a commit // which is no longer a pull's head commit. if (pullNumber === null) { - debug( + dbDebug( "updateCommitStatus: commit %s is not the HEAD of any pull, none to refresh in repo %s", sha, repo @@ -143,7 +145,7 @@ var dbManager = (module.exports = { } queue.markPullAsDirty(dbStatus.data.repo, pullNumber); - debug( + dbDebug( "updateCommitStatus: updated status of Pull #%s in repo %s", pullNumber, dbStatus.data.repo @@ -156,7 +158,7 @@ var dbManager = (module.exports = { * it already exists. */ updateComment: function (comment) { - debug( + dbDebug( "Calling `updateComment` for comment %s in repo %s", comment.data.comment_id, comment.data.repo @@ -167,7 +169,7 @@ var dbManager = (module.exports = { return dbComment.save().then(function () { queue.markPullAsDirty(repo, number); - debug( + dbDebug( "updateComment: updated comment(%s) on Pull #%s in repo %s", dbComment.data.comment_id, number, @@ -181,7 +183,7 @@ var dbManager = (module.exports = { * it already exists. */ updateReview: function (review) { - debug( + dbDebug( "Calling `updateReview` for review %s in repo %s", review.data.review_id, review.data.repo @@ -192,7 +194,7 @@ var dbManager = (module.exports = { return dbReview.save().then(function () { queue.markPullAsDirty(repo, number); - debug( + dbDebug( "updateReview: updated review(%s) on Pull #%s in repo %s", dbReview.data.review_id, number, @@ -207,7 +209,7 @@ var dbManager = (module.exports = { * DB writes are complete. */ insertSignature: function (signature) { - debug( + dbDebug( "Calling insertSignature for pull #%s in repo %s", signature.data.number, signature.data.repo @@ -231,7 +233,7 @@ var dbManager = (module.exports = { } return invalidate.then(function () { - debug( + dbDebug( "insertSignature: saving %s(%s) on Pull #%s in repo %s", type, signature.data.comment_id, @@ -271,7 +273,7 @@ var dbManager = (module.exports = { * Insert a single label into the DB. */ insertLabel: function (label) { - debug( + dbDebug( "Calling insertLabel for label '%s' on pull #%s in repo %s", label.data.title, label.data.number, @@ -301,7 +303,7 @@ var dbManager = (module.exports = { * @param types - array of types to invalidate */ invalidateSignatures: function (repo, number, types) { - debug("Calling invalidateSignatures for pull #%s in repo %s", number, repo); + dbDebug("Calling invalidateSignatures for pull #%s in repo %s", number, repo); var q_update = "\ UPDATE pull_signatures \ @@ -309,7 +311,7 @@ var dbManager = (module.exports = { WHERE repo = ? AND number = ? AND type IN ?"; return db.query(q_update, [repo, number, [types]]).then(function () { - debug( + dbDebug( "invalidateSignatures: invalidated %ss on Pull #%s in repo %s", types, number, @@ -323,7 +325,7 @@ var dbManager = (module.exports = { * number built from data stored in the database. */ getPull: function (repo, number) { - debug("Calling getPull for pull #%s in repo %s", number, repo); + dbDebug("Calling getPull for pull #%s in repo %s", number, repo); var self = this; var q_select = "\ @@ -355,7 +357,7 @@ var dbManager = (module.exports = { labels = resolved[3]; reviews = resolved[4]; - debug("getPull: retrieved Pull #%s in repo %s", number, repo); + dbDebug("getPull: retrieved Pull #%s in repo %s", number, repo); return Pull.getFromDB( dbPullData, signatures, @@ -373,7 +375,7 @@ var dbManager = (module.exports = { * number built from data stored in the database. */ getIssue: function (repo, number) { - debug("Calling getIssue for issue #%s in repo %s", number, repo); + dbDebug("Calling getIssue for issue #%s in repo %s", number, repo); var q_select = "SELECT * FROM issues WHERE number = ? AND repo = ?"; return db.query(q_select, [number, repo]).then(function (rows) { @@ -383,7 +385,7 @@ var dbManager = (module.exports = { var dbIssueData = rows[0]; return dbManager.getLabels(repo, number).then(function (labels) { - debug("getIssue: retrieved issue #%s in repo %s", number, repo); + dbDebug("getIssue: retrieved issue #%s in repo %s", number, repo); return Issue.getFromDB(dbIssueData, labels); }); }); @@ -408,14 +410,14 @@ var dbManager = (module.exports = { getRecentPulls: function (includeMergedSince) { var self = this; const mergedSinceUnix = Math.floor(includeMergedSince.getTime() / 1000); - debug("Calling getRecentPulls"); + dbDebug("Calling getRecentPulls"); var q_select = "SELECT repo, number FROM pulls WHERE state = ? OR date_closed > ?"; return db .query(q_select, ["open", mergedSinceUnix]) .then(function (rows) { - debug("Found %s open pulls in the DB", rows.length); + dbDebug("Found %s open pulls in the DB", rows.length); if (rows.length === 0) { return []; } @@ -503,13 +505,13 @@ var dbManager = (module.exports = { * Returns a promise which resolves to an array of labels for the pull. */ getLabels: function getLabels(repo, number) { - debug("Calling getLabels for #%s in repo %s", number, repo); + dbDebug("Calling getLabels for #%s in repo %s", number, repo); var q_select = "\ SELECT * FROM pull_labels \ WHERE number = ? AND repo = ?"; return db.query(q_select, [number, repo]).then(function (rows) { - debug("Got %s rows", rows.length); + dbDebug("Got %s rows", rows.length); return rows.map(function (row) { return Label.getFromDB(row); }); @@ -521,11 +523,11 @@ var dbManager = (module.exports = { * the given pull number have been removed from the database. */ deleteSignatures: function (repo, number) { - debug("Calling deleteSignatures for pull #%s in repo %s", number, repo); + dbDebug("Calling deleteSignatures for pull #%s in repo %s", number, repo); var q_delete = "DELETE FROM pull_signatures WHERE number = ? AND repo = ?"; return db.query(q_delete, [number, repo]).then(function () { - debug( + dbDebug( "deleteSignatures: deleting from Pull #%s in repo %s", number, repo @@ -537,7 +539,7 @@ var dbManager = (module.exports = { * Delete a single label from the database. */ deleteLabel: function deleteLabel(label) { - debug( + dbDebug( "Calling deleteLabel for label '%s' on issue #%s", label.data.title, label.data.number @@ -557,7 +559,7 @@ var dbManager = (module.exports = { * have been deleted from the database. */ deleteLabels: function deleteLabels(repo, number) { - debug("Calling deleteLabels for pull #%s in repo %s", number, repo); + dbDebug("Calling deleteLabels for pull #%s in repo %s", number, repo); var q_delete = "DELETE FROM pull_labels WHERE number = ? AND repo = ?"; return db.query(q_delete, [number, repo]); }, @@ -566,7 +568,9 @@ var dbManager = (module.exports = { // updates closed pulls that are still set as 'open' in the DB, but have // since been closed. // @TODO closeStalePulls: -}); +}; + +export default dbManager; /** * Return a copy of the specified array with nulls removed diff --git a/lib/db.js b/lib/db.js index 1b127404..36a5d47a 100644 --- a/lib/db.js +++ b/lib/db.js @@ -1,5 +1,6 @@ -var mysql = require("mysql2/promise"), - config = require("./config-loader"); +import mysql from "mysql2/promise"; +import config from "./config-loader.js"; +import EncodingToCharset from "../node_modules/mysql2/lib/constants/encoding_charset.js"; // OMG, this took forever to figure out // Add support for understanding utf8mb3 charset to the mysql2 library @@ -7,19 +8,20 @@ var mysql = require("mysql2/promise"), // We don't have any utf8mb3 columns, but if you run a query that generates // no result (DELETE, REPLACE, ...) it will return metadata indicating that the // empty result is in the "servers" charset, which is utf8mb3 (still) -var EncodingToCharset = require("../node_modules/mysql2/lib/constants/encoding_charset"); + +// Add support for utf8mb3 charset EncodingToCharset.utf8mb3 = 192; const pool = mysql.createPool({ - host: config.mysql.host, - database: config.mysql.db, - user: config.mysql.user, - password: config.mysql.pass, - charset: "utf8mb4", + host: config.mysql.host, + database: config.mysql.db, + user: config.mysql.user, + password: config.mysql.pass, + charset: "utf8mb4", }); -module.exports = { - query: function(query, params) { +export default { + query: function (query, params) { return pool.query(query, params) .then((result) => result[0]); // [rows, fields] } diff --git a/lib/debug.js b/lib/debug.js index 1d564894..bffe948e 100644 --- a/lib/debug.js +++ b/lib/debug.js @@ -1,8 +1,9 @@ -var debug = require("debug"); -module.exports = debug; +import debug from "debug"; if (process.env.NO_TIMESTAMP) { debug.formatArgs = function (args) { args[0] = this.namespace + " " + args[0] + " +" + debug.humanize(this.diff); }; } + +export default debug; diff --git a/lib/get-user-id.js b/lib/get-user-id.js index fb2d7917..9473a235 100644 --- a/lib/get-user-id.js +++ b/lib/get-user-id.js @@ -1,7 +1,7 @@ -module.exports = function (userApiObject) { +export default function getUserId(userApiObject) { // 10137 is the userid of the "ghost" user // https://api.github.com/users/ghost // All deleted users are replaced with references to this user within github // (except in the api, where they are just null return userApiObject ? userApiObject.id : 10137; -}; +} diff --git a/lib/get-user-login.js b/lib/get-user-login.js index fc6d459f..8e378f5e 100644 --- a/lib/get-user-login.js +++ b/lib/get-user-login.js @@ -1,6 +1,6 @@ -module.exports = function (userApiObject) { +export default function getUserLogin(userApiObject) { // All deleted users are replaced with references to this user within // the github web app (except in the api, where they are just null). // https://github.com/ghost return userApiObject ? userApiObject.login : "ghost"; -}; +} diff --git a/lib/git-manager.js b/lib/git-manager.js index 4cfdc7f0..9c31b82c 100644 --- a/lib/git-manager.js +++ b/lib/git-manager.js @@ -1,19 +1,23 @@ -var { Octokit } = require("@octokit/rest"), - { throttling } = require("@octokit/plugin-throttling"), - MyOctokit = Octokit.plugin(throttling), - config = require("./config-loader"), - Promise = require("bluebird"), - _ = require("underscore"), - debug = require("./debug")("pulldasher:github"), - utils = require("./utils"), - Pull = require("../models/pull"), - Issue = require("../models/issue"), - Comment = require("../models/comment"), - Review = require("../models/review"), - Label = require("../models/label"), - Status = require("../models/status"), - Signature = require("../models/signature"), - getLogin = require("./get-user-login"); +import { Octokit } from "@octokit/rest"; +import { throttling } from "@octokit/plugin-throttling"; +import config from "./config-loader.js"; +import Promise from "bluebird"; +import _ from "underscore"; +import debug from "./debug.js"; +import utils from "./utils.js"; +import Pull from "../models/pull.js"; +import Issue from "../models/issue.js"; +import Comment from "../models/comment.js"; +import Review from "../models/review.js"; +import Label from "../models/label.js"; +import Status from "../models/status.js"; +import Signature from "../models/signature.js"; +import getLogin from "./get-user-login.js"; + +const MyOctokit = Octokit.plugin(throttling); +const gitDebug = debug("pulldasher:github"); + +console.log(config.github); const github = new MyOctokit({ auth: config.github.token, @@ -29,6 +33,12 @@ const github = new MyOctokit({ return true; } }, + onSecondaryRateLimit: (retryAfter, options) => { + // does not retry, only logs a warning + github.log.warn( + `SecondaryRateLimit detected for request ${options.method} ${options.url}`, + ); + }, onAbuseLimit: (retryAfter, options) => { // does not retry, only logs a warning github.log.warn( @@ -40,7 +50,7 @@ const github = new MyOctokit({ const githubRest = github.rest; -module.exports = { +export default { github: githubRest, /** @@ -88,18 +98,7 @@ module.exports = { * * Returns a promise which resolves to a github issue */ - getIssue: function (repo, number) { - const searchParams = params({ issue_number: number }, repo); - return logErrors( - githubRest.issues - .get(searchParams) - .then((res) => res.data) - .then(addRepo(searchParams)), - "Getting issue %s in repo %s", - number, - repo - ); - }, + getIssue, /** * Get all open issues for a repo. @@ -140,7 +139,7 @@ module.exports = { * parses it, and returns a promise that resolves to a Pull objects. */ parse: function (githubPull) { - debug( + gitDebug( "Getting all information for pull %s in repo %s", githubPull.number, githubPull.base.repo.full_name @@ -158,7 +157,7 @@ module.exports = { var jobRuns = getAllJobRuns(repo, githubPull.head.sha); var events = getIssueEvents(repo, githubPull.number); // Only so we have the canonical list of labels. - var ghIssue = module.exports.getIssue(repo, githubPull.number); + var ghIssue = getIssue(repo, githubPull.number); var reviews = getReviews(repo, githubPull.number); // Returned to the map function. Each element of githubPulls maps to @@ -295,7 +294,7 @@ module.exports = { * parses it, and returns a promise that resolves to an Issue object. */ parseIssue: function (ghIssue) { - debug( + gitDebug( "Getting all information for issue %s in repo %s", ghIssue.number, ghIssue.repo @@ -311,6 +310,19 @@ module.exports = { }, }; +function getIssue(repo, number) { + const searchParams = params({ issue_number: number }, repo); + return logErrors( + githubRest.issues + .get(searchParams) + .then((res) => res.data) + .then(addRepo(searchParams)), + "Getting issue %s in repo %s", + number, + repo + ); +} + /** * Get array of Label objects from complete list of a Issue's events. * @@ -319,7 +331,7 @@ module.exports = { * issue.repo property. */ function getLabelsFromEvents(events, ghIssue) { - debug( + gitDebug( "Extracting label assignments from %s issue events for #%s", events.length, ghIssue.number @@ -330,7 +342,7 @@ function getLabelsFromEvents(events, ghIssue) { return event.event === "labeled" || event.event === "unlabeled"; }); - debug("Found %s label events for #%s", events.length, ghIssue.number); + gitDebug("Found %s label events for #%s", events.length, ghIssue.number); // Build simple Event objects with all the info we care about. events = events.map(function (event) { @@ -355,14 +367,14 @@ function getLabelsFromEvents(events, ghIssue) { return event.type === "labeled"; }); - debug("Found %s unique labels for #%s", labels.length, ghIssue.number); + gitDebug("Found %s unique labels for #%s", labels.length, ghIssue.number); // If these are available, use them as the canonical source, only augmented // by the data from events. If a label is renamed, the events will retain // the old name but the list of labels on the issue itself will be correct. // So, if a label is renamed, we'll lose the labeler and the date. if (ghIssue.labels && ghIssue.labels.length) { - debug("Using %s labels from the github issue", ghIssue.labels.length); + gitDebug("Using %s labels from the github issue", ghIssue.labels.length); // Includes labeller and a time from the events api var eventLabels = _.indexBy(labels, "name"); @@ -551,20 +563,20 @@ function getJobRunsFromWorkflow(workflowRun) { * Remove all entries that have the pull_request key set to something truthy */ function filterOutPulls(issues) { - debug("Filtering out pulls from list of %s issues", issues.length); + gitDebug("Filtering out pulls from list of %s issues", issues.length); issues = _.filter( issues, (issue) => !issue.pull_request || !issue.pull_request.url ); - debug("Filtered down to %s issues", issues.length); + gitDebug("Filtered down to %s issues", issues.length); return issues; } function logErrors(promise, ...messageAndArgs) { - debug(...messageAndArgs); + gitDebug(...messageAndArgs); return promise.catch((err) => { messageAndArgs[0] = "Error: Failed while: " + messageAndArgs[0]; - debug(...messageAndArgs); + gitDebug(...messageAndArgs); throw err; }); } diff --git a/lib/pull-manager.js b/lib/pull-manager.js index 46109443..d432ae1b 100644 --- a/lib/pull-manager.js +++ b/lib/pull-manager.js @@ -1,13 +1,15 @@ -var debug = require("./debug")("pulldasher:pull-manager"), - pullQueue = require("./pull-queue"), - config = require("./config-loader"), - _ = require("underscore"), - dbManager = require("./db-manager"); +import debug from "./debug.js"; +import pullQueue from "./pull-queue.js"; +import config from "./config-loader.js"; +import _ from "underscore"; +import dbManager from "./db-manager.js"; -var sockets = []; -var pulls = []; +const pmDebug = debug("pulldasher:pull-manager"); -var pullManager = (module.exports = { +const sockets = []; +let pulls = []; + +const pullManager = { getOldestAllowedPullTimestamp: function () { // Keep the same or higher than the value in leader-list.tsx const includePullsClosedWithinDays = 14; @@ -34,10 +36,10 @@ var pullManager = (module.exports = { notifyAboutPullStateChange(pull); }, -}); +}; function sendInitialData(socket) { - debug("Emitting `initialize`: %s pulls altogether", pulls.length); + pmDebug("Emitting `initialize`: %s pulls altogether", pulls.length); socket.emit("initialize", { pulls: _.invoke(pulls, "toObject"), repos: config.repos, @@ -45,7 +47,7 @@ function sendInitialData(socket) { } function notifyAboutPullStateChange(pull) { - debug( + pmDebug( "Emitting `pullChange`: sending Pull #%s in repo %s to %s sockets", pull.data.number, pull.data.repo, @@ -76,7 +78,7 @@ function getPull(repo, number) { pullQueue.on("pullsChanged", function (pulls) { pulls.forEach(function (pullId) { - debug( + pmDebug( "Got pull changed event, loading pull #%s in repo %s from DB.", pullId.number, pullId.repo @@ -99,3 +101,5 @@ setTimeout(() => { pull.data.closed_at > oldestAllowed ); }, 3600 * 1000); + +export default pullManager; diff --git a/lib/pull-queue.js b/lib/pull-queue.js index 3c9b5718..bdcbfb35 100644 --- a/lib/pull-queue.js +++ b/lib/pull-queue.js @@ -1,12 +1,13 @@ -var events = require("events"), - _ = require("underscore"); +import events from "events"; +import _ from "underscore"; +import { inherits } from "util"; function PullQueue() { events.EventEmitter.call(this); this.dirtyPulls = {}; } -require("util").inherits(PullQueue, events.EventEmitter); +inherits(PullQueue, events.EventEmitter); _.extend(PullQueue.prototype, { /** @@ -39,4 +40,4 @@ _.extend(PullQueue.prototype, { }, }); -module.exports = new PullQueue(); +export default new PullQueue(); diff --git a/lib/refresh.js b/lib/refresh.js index de59290b..d2ba9ad6 100644 --- a/lib/refresh.js +++ b/lib/refresh.js @@ -1,32 +1,33 @@ -var gitManager = require("./git-manager"); -var dbManager = require("./db-manager"); -var utils = require("./utils"); - -var NotifyQueue = require("notify-queue"); -var debug = require("./debug")("pulldasher:refresh"); -var Promise = require("bluebird"); +import gitManager from "./git-manager.js"; +import dbManager from "./db-manager.js"; +import utils from "./utils.js"; +import NotifyQueue from "notify-queue"; +import debug from "./debug.js"; +import Promise from "bluebird"; // Queues for making all refreshes be synchronous, one at a time. var issueQueue = new NotifyQueue(); var pullQueue = new NotifyQueue(); -module.exports = { +const refreshDebug = debug("pulldasher:refresh"); + +export default { /////// Issues ///////// issue: function refreshIssue(repo, number) { - debug("refresh issue %s", number); + refreshDebug("refresh issue %s", number); return gitManager.getIssue(repo, number).then(pushOnQueue(issueQueue)); }, allIssues: function refreshOpenIssues() { - debug("refresh all issues"); + refreshDebug("refresh all issues"); return utils .forEachRepo(gitManager.getAllIssues) .then(pushAllOnQueue(issueQueue)); }, openIssues: function refreshOpenIssues() { - debug("refresh all open issues"); + refreshDebug("refresh all open issues"); return utils .forEachRepo(gitManager.getOpenIssues) .then(pushAllOnQueue(issueQueue)); @@ -35,19 +36,19 @@ module.exports = { /////// Pulls ///////// pull: function refreshPull(repo, number) { - debug("refresh pull %s", number); + refreshDebug("refresh pull %s", number); return gitManager.getPull(repo, number).then(pushOnQueue(pullQueue)); }, allPulls: function refreshAllPulls() { - debug("refresh all pull"); + refreshDebug("refresh all pull"); return utils .forEachRepo(gitManager.getAllPulls) .then(pushAllOnQueue(pullQueue)); }, openPulls: function refreshOpenPulls() { - debug("refresh all open pulls"); + refreshDebug("refresh all open pulls"); return utils .forEachRepo(gitManager.getOpenPulls) .then(pushAllOnQueue(pullQueue)); @@ -92,12 +93,12 @@ issueQueue.pop(function (githubIssue, next) { githubIssue(); return next(); } - debug("refreshing issue %s", githubIssue.number); + refreshDebug("refreshing issue %s", githubIssue.number); gitManager .parseIssue(githubIssue) .then(dbManager.updateAllIssueData) .done(function () { - debug( + refreshDebug( "done refreshing issue %s in repo %s", githubIssue.number, githubIssue.repo @@ -113,7 +114,7 @@ pullQueue.pop(function (githubPull, next) { githubPull(); return next(); } - debug( + refreshDebug( "refreshing pull %s in repo %s", githubPull.number, githubPull.base.repo.full_name @@ -122,7 +123,7 @@ pullQueue.pop(function (githubPull, next) { .parse(githubPull) .then(dbManager.updateAllPullData) .done(function () { - debug("done refreshing pull %s", githubPull.number); + refreshDebug("done refreshing pull %s", githubPull.number); next(); }); }); diff --git a/lib/socket-auth.js b/lib/socket-auth.js index 8f189cc2..50e6a65c 100644 --- a/lib/socket-auth.js +++ b/lib/socket-auth.js @@ -1,27 +1,25 @@ -var config = require("./config-loader"); -var users = {}; +import config from "./config-loader.js"; -var token_timeout = - config.token_timeout !== undefined ? config.token_timeout : 100 * 1000; +const users = {}; +const token_timeout = config.token_timeout !== undefined ? config.token_timeout : 100 * 1000; -module.exports = { +function random() { + return Math.random().toString(36).substr(2); +} + +export default { getTokenForUser: function (user) { - var token = random(); + const token = random(); users[token] = { expires: Date.now() + token_timeout, - user: user, + user: user }; return token; }, retrieveUser: function (token) { - var user = users[token]; + const user = users[token]; delete users[token]; return user && user.expires > Date.now() && user.user; - }, + } }; - -// Returns a random string -function random() { - return Math.random().toString(36).substr(2); -} diff --git a/lib/utils.js b/lib/utils.js index 94fd0571..be443829 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -1,16 +1,15 @@ -var config = require("./config-loader"), - Bluebird = require("bluebird"), - Promise = global.Promise, - _ = require("underscore"); +import config from "./config-loader.js"; +import Bluebird from "bluebird"; +import _ from "underscore"; -// Set the global Promise object up with the done method so that any -// promise by other libraries will have a .done() +const Promise = global.Promise; + +// Set the global Promise object up with the done method Promise.prototype.done = function (callback) { return Bluebird.cast(this).done(callback); }; -Promise = Bluebird; -module.exports = { +export default { /** * Converts `t` to a Unix timestamp from a Date object unless it's already * a number. diff --git a/models/comment.js b/models/comment.js index 98ce4249..3ee15556 100644 --- a/models/comment.js +++ b/models/comment.js @@ -1,37 +1,39 @@ -var utils = require("../lib/utils"); -var getLogin = require("../lib/get-user-login"); +import utils from "../lib/utils.js"; +import getLogin from "../lib/get-user-login.js"; /** * A Pull Request comment. */ -function Comment(data) { - this.data = { - number: data.number, - repo: data.repo, - user: { - login: getLogin(data.user), - }, - created_at: new Date(data.created_at), - comment_type: data.type, - comment_id: data.id, - }; -} +class Comment { + constructor(data) { + this.data = { + number: data.number, + repo: data.repo, + user: { + login: getLogin(data.user), + }, + created_at: new Date(data.created_at), + comment_type: data.type, + comment_id: data.id, + }; + } -/** - * Takes an object representing a DB row, and returns an instance of this - * Comment object. - */ -Comment.getFromDB = function (data) { - return new Comment({ - number: data.number, - repo: data.repo, - user: { - login: data.user, - }, - created_at: utils.fromUnixTime(data.date), - type: data.comment_type, - id: data.comment_id, - }); -}; + /** + * Takes an object representing a DB row, and returns an instance of this + * Comment object. + */ + static getFromDB(data) { + return new Comment({ + number: data.number, + repo: data.repo, + user: { + login: data.user, + }, + created_at: utils.fromUnixTime(data.date), + type: data.comment_type, + id: data.comment_id, + }); + } +} -module.exports = Comment; +export default Comment; diff --git a/models/db_comment.js b/models/db_comment.js index 9ee21d03..ca5202d1 100644 --- a/models/db_comment.js +++ b/models/db_comment.js @@ -1,42 +1,45 @@ -var utils = require("../lib/utils"), - db = require("../lib/db"), - getLogin = require("../lib/get-user-login"), - debug = require("../lib/debug")("pulldasher:db_comment"); +import utils from "../lib/utils.js"; +import db from "../lib/db.js"; +import getLogin from "../lib/get-user-login.js"; +import debug from "../lib/debug.js"; + +const log = debug("pulldasher:db_comment"); /** * Builds an object representation of a row in the DB `comments` table * from the Comment object. */ -function DBComment(comment) { - var commentData = comment.data; - this.data = { - number: commentData.number, - repo: commentData.repo, - user: getLogin(commentData.user), - date: utils.toUnixTime(commentData.created_at), - comment_type: commentData.comment_type, - comment_id: commentData.comment_id, - }; -} +class DBComment { + constructor(comment) { + const commentData = comment.data; + this.data = { + number: commentData.number, + repo: commentData.repo, + user: getLogin(commentData.user), + date: utils.toUnixTime(commentData.created_at), + comment_type: commentData.comment_type, + comment_id: commentData.comment_id, + }; + } -DBComment.prototype.save = function () { - var commentData = this.data; - var q_update = "REPLACE INTO comments SET ?"; + save() { + const commentData = this.data; + const q_update = "REPLACE INTO comments SET ?"; + return db.query(q_update, commentData); + } - return db.query(q_update, commentData); -}; - -DBComment.delete = function deleteComment(repo, type, comment_id) { - debug("deleting %s comment %s in repo %s", type, comment_id, repo); - var q_delete = - "DELETE FROM comments \ + static delete(repo, type, comment_id) { + log("deleting %s comment %s in repo %s", type, comment_id, repo); + const q_delete = + "DELETE FROM comments \ WHERE `comment_type` = ? \ AND `comment_id` = ? \ AND `repo` = ?"; - return db.query(q_delete, [type, comment_id, repo]).then(function () { - debug("deleted %s comment %s in repo %s", type, comment_id, repo); - }); -}; + return db.query(q_delete, [type, comment_id, repo]).then(() => { + log("deleted %s comment %s in repo %s", type, comment_id, repo); + }); + } +} -module.exports = DBComment; +export default DBComment; diff --git a/models/db_issue.js b/models/db_issue.js index 90e86b25..2453c77a 100644 --- a/models/db_issue.js +++ b/models/db_issue.js @@ -1,46 +1,47 @@ -var utils = require("../lib/utils"); -var db = require("../lib/db"); +import utils from "../lib/utils.js"; +import db from "../lib/db.js"; /** * Create a new instance from an Issue object */ -function DBIssue(issue) { - this.data = { - repo: issue.repo, - number: issue.number, - title: issue.title, - assignee: issue.assignee, - status: issue.status, - date_created: utils.toUnixTime(issue.date_created), - date_closed: utils.toUnixTime(issue.date_closed), - difficulty: issue.difficulty, - }; +class DBIssue { + constructor(issue) { + this.data = { + repo: issue.repo, + number: issue.number, + title: issue.title, + assignee: issue.assignee, + status: issue.status, + date_created: utils.toUnixTime(issue.date_created), + date_closed: utils.toUnixTime(issue.date_closed), + difficulty: issue.difficulty, + }; - if (issue.milestone) { - this.data.milestone_title = issue.milestone.title; - this.data.milestone_due_on = utils.toUnixTime(issue.milestone.due_on); - } else { - this.data.milestone_title = null; - this.data.milestone_due_on = null; - } -} - -DBIssue.findByNumber = function (repo, number) { - var q_select = "SELECT * FROM `issues` WHERE `number` = ? AND repo = ?"; - return db.query(q_select, [repo, number]).then(function (rows) { - if (rows) { - return rows[0]; + if (issue.milestone) { + this.data.milestone_title = issue.milestone.title; + this.data.milestone_due_on = utils.toUnixTime(issue.milestone.due_on); } else { - return null; + this.data.milestone_title = null; + this.data.milestone_due_on = null; } - }); -}; + } -DBIssue.prototype.save = function () { - var issueData = this.data; - var q_update = "REPLACE INTO issues SET ?"; + static findByNumber(repo, number) { + const q_select = "SELECT * FROM `issues` WHERE `number` = ? AND repo = ?"; + return db.query(q_select, [repo, number]).then((rows) => { + if (rows) { + return rows[0]; + } else { + return null; + } + }); + } - return db.query(q_update, issueData); -}; + save() { + const issueData = this.data; + const q_update = "REPLACE INTO issues SET ?"; + return db.query(q_update, issueData); + } +} -module.exports = DBIssue; +export default DBIssue; diff --git a/models/db_label.js b/models/db_label.js index d1a6794e..2ce7853f 100644 --- a/models/db_label.js +++ b/models/db_label.js @@ -1,36 +1,37 @@ -var utils = require("../lib/utils"), - db = require("../lib/db"); +import utils from "../lib/utils.js"; +import db from "../lib/db.js"; // Builds an object representation of a row in the DB `pull_labels` table // from an instance of the Label model -function DBLabel(label) { - var labelData = label.data; - this.data = { - number: labelData.number, - title: labelData.title, - repo: labelData.repo, - user: labelData.user, - date: utils.toUnixTime(labelData.created_at), - }; -} - -DBLabel.prototype.save = function () { - var labelData = this.data; - var q_update = "REPLACE INTO pull_labels SET ?"; +class DBLabel { + constructor(label) { + const labelData = label.data; + this.data = { + number: labelData.number, + title: labelData.title, + repo: labelData.repo, + user: labelData.user, + date: utils.toUnixTime(labelData.created_at), + }; + } - return db.query(q_update, labelData); -}; + save() { + const labelData = this.data; + const q_update = "REPLACE INTO pull_labels SET ?"; + return db.query(q_update, labelData); + } -DBLabel.prototype.delete = function () { - var labelData = this.data; - var q_update = - "DELETE FROM pull_labels WHERE " + "number = ? AND title = ? AND repo = ?"; + delete() { + const labelData = this.data; + const q_update = + "DELETE FROM pull_labels WHERE " + "number = ? AND title = ? AND repo = ?"; - return db.query(q_update, [ - labelData.number, - labelData.title, - labelData.repo, - ]); -}; + return db.query(q_update, [ + labelData.number, + labelData.title, + labelData.repo, + ]); + } +} -module.exports = DBLabel; +export default DBLabel; diff --git a/models/db_pull.js b/models/db_pull.js index 6e8d67d3..f762fd9a 100644 --- a/models/db_pull.js +++ b/models/db_pull.js @@ -1,6 +1,6 @@ -var utils = require("../lib/utils"), - getLogin = require("../lib/get-user-login"), - db = require("../lib/db"); +import utils from "../lib/utils.js"; +import getLogin from "../lib/get-user-login.js"; +import db from "../lib/db.js"; // Builds an object representation of a row in the DB `pulls` table // from the data returned by GitHub's API. @@ -43,4 +43,4 @@ DBPull.prototype.save = function () { return db.query(q_update, pullData); }; -module.exports = DBPull; +export default DBPull; diff --git a/models/db_review.js b/models/db_review.js index c6b0f0a1..cfaf387b 100644 --- a/models/db_review.js +++ b/models/db_review.js @@ -1,42 +1,45 @@ -var utils = require("../lib/utils"), - db = require("../lib/db"), - getLogin = require("../lib/get-user-login"), - debug = require("../lib/debug")("pulldasher:db_review"); +import utils from "../lib/utils.js"; +import db from "../lib/db.js"; +import getLogin from "../lib/get-user-login.js"; +import debug from "../lib/debug.js"; + +const log = debug("pulldasher:db_review"); /** * Builds an object representation of a row in the DB `reviews` table * from the Review object. */ -function DBReview(review) { - var reviewData = review.data; - this.data = { - repo: reviewData.repo, - review_id: reviewData.review_id, - number: reviewData.number, - body: reviewData.body, - state: reviewData.state, - user: getLogin(reviewData.user), - date: utils.toUnixTime(reviewData.submitted_at), - }; -} +class DBReview { + constructor(review) { + const reviewData = review.data; + this.data = { + repo: reviewData.repo, + review_id: reviewData.review_id, + number: reviewData.number, + body: reviewData.body, + state: reviewData.state, + user: getLogin(reviewData.user), + date: utils.toUnixTime(reviewData.submitted_at), + }; + } -DBReview.prototype.save = function () { - var reviewData = this.data; - var q_update = "REPLACE INTO reviews SET ?"; + save() { + const reviewData = this.data; + const q_update = "REPLACE INTO reviews SET ?"; + return db.query(q_update, reviewData); + } - return db.query(q_update, reviewData); -}; - -DBReview.delete = function deleteReview(repo, review_id) { - debug("deleting %s review %s in repo %s", review_id, repo); - var q_delete = - "DELETE FROM reviews \ + static delete(repo, review_id) { + log("deleting %s review %s in repo %s", review_id, repo); + const q_delete = + "DELETE FROM reviews \ WHERE `review_id` = ? \ AND `repo` = ?"; - return db.query(q_delete, [review_id, repo]).then(function () { - debug("deleted %s review %s in repo %s", review_id, repo); - }); -}; + return db.query(q_delete, [review_id, repo]).then(() => { + log("deleted %s review %s in repo %s", review_id, repo); + }); + } +} -module.exports = DBReview; +export default DBReview; diff --git a/models/db_signature.js b/models/db_signature.js index d768a145..30122335 100644 --- a/models/db_signature.js +++ b/models/db_signature.js @@ -1,31 +1,32 @@ -var utils = require("../lib/utils"), - getLogin = require("../lib/get-user-login"), - getUserid = require("../lib/get-user-id"), - db = require("../lib/db"); +import utils from "../lib/utils.js"; +import getLogin from "../lib/get-user-login.js"; +import getUserid from "../lib/get-user-id.js"; +import db from "../lib/db.js"; /** * Builds an object representation of a row in the DB `pull_signatures` table * from the Signature object. */ -function DBSignature(signature) { - var sigData = signature.data; - this.data = { - repo: sigData.repo, - number: sigData.number, - user: getLogin(sigData.user), - userid: getUserid(sigData.user), - type: sigData.type, - date: utils.toUnixTime(sigData.created_at), - active: sigData.active, - comment_id: sigData.comment_id, - }; -} - -DBSignature.prototype.save = function () { - var sigData = this.data; - var q_insert = "INSERT INTO pull_signatures SET ?"; +class DBSignature { + constructor(signature) { + const sigData = signature.data; + this.data = { + repo: sigData.repo, + number: sigData.number, + user: getLogin(sigData.user), + userid: getUserid(sigData.user), + type: sigData.type, + date: utils.toUnixTime(sigData.created_at), + active: sigData.active, + comment_id: sigData.comment_id, + }; + } - return db.query(q_insert, sigData); -}; + save() { + const sigData = this.data; + const q_insert = "INSERT INTO pull_signatures SET ?"; + return db.query(q_insert, sigData); + } +} -module.exports = DBSignature; +export default DBSignature; diff --git a/models/db_status.js b/models/db_status.js index c100bba6..b037c09f 100644 --- a/models/db_status.js +++ b/models/db_status.js @@ -1,31 +1,32 @@ -var _ = require("underscore"), - db = require("../lib/db"); +import _ from "underscore"; +import db from "../lib/db.js"; // Builds an object representation of a row in the DB `commit_statuses` // table from an instance of the Status model -function DBStatus(status) { - var statusData = status.data; - this.data = { - repo: statusData.repo, - commit: statusData.sha, - state: statusData.state, - description: statusData.description, - log_url: statusData.target_url, - context: statusData.context, - started_at: statusData.started_at, - completed_at: statusData.completed_at, - }; -} - -DBStatus.prototype.save = function () { - var statusData = this.data; - var q_update = "REPLACE INTO commit_statuses SET ?"; +class DBStatus { + constructor(status) { + const statusData = status.data; + this.data = { + repo: statusData.repo, + commit: statusData.sha, + state: statusData.state, + description: statusData.description, + log_url: statusData.target_url, + context: statusData.context, + started_at: statusData.started_at, + completed_at: statusData.completed_at, + }; + } - return db.query(q_update, statusData); -}; + save() { + const statusData = this.data; + const q_update = "REPLACE INTO commit_statuses SET ?"; + return db.query(q_update, statusData); + } -DBStatus.prototype.toObject = function () { - return _.extend({}, this.data); -}; + toObject() { + return _.extend({}, this.data); + } +} -module.exports = DBStatus; +export default DBStatus; diff --git a/models/issue.js b/models/issue.js index 069ed568..22b25df9 100644 --- a/models/issue.js +++ b/models/issue.js @@ -1,112 +1,116 @@ -var utils = require("../lib/utils"); -var _ = require("underscore"); -var config = require("../lib/config-loader"); -var log = require("../lib/debug")("pulldasher:issue"); -var DBIssue = require("./db_issue"); -var getLogin = require("../lib/get-user-login"); +import utils from "../lib/utils.js"; +import _ from "underscore"; +import config from "../lib/config-loader.js"; +import log from "../lib/debug.js"; +import DBIssue from "./db_issue.js"; +import getLogin from "../lib/get-user-login.js"; + +const debug = log("pulldasher:issue"); /** * Create a new issue. Not meant to be used directly, see * Issue.getFromGH or Issue.getFromDB */ -function Issue(data, labels) { - _.extend(this, data); - if (labels) { - this.updateFromLabels(labels); +class Issue { + constructor(data, labels) { + _.extend(this, data); + if (labels) { + this.updateFromLabels(labels); + } } -} -Issue.findByNumber = function (repo, number) { - return DBIssue.findByNumber(repo, number).then(Issue.getFromDB); -}; + static findByNumber(repo, number) { + return DBIssue.findByNumber(repo, number).then(Issue.getFromDB); + } -/** - * Create properties on this object for each label it has of the configured - * labels. - * - * @labels: array of Label objects - */ -Issue.prototype.updateFromLabels = function (labels) { - var self = this; - if (labels) { - log("Processing %s labels on #%s", labels.length, self.number); - (config.labels || []).forEach(function (labelConfig) { - self[labelConfig.name] = null; - labels.forEach(function (label) { - var labelName = label.data.title; - log( - "Testing label '%s' against regex %s", - labelName, - labelConfig.regex - ); - if (labelConfig.regex.test(labelName)) { - log( - "Setting %s on #%s because of a label reading %s", - labelConfig.name, - self.number, - labelName + /** + * Create properties on this object for each label it has of the configured + * labels. + * + * @labels: array of Label objects + */ + updateFromLabels(labels) { + const self = this; + if (labels) { + debug("Processing %s labels on #%s", labels.length, self.number); + (config.labels || []).forEach((labelConfig) => { + self[labelConfig.name] = null; + labels.forEach((label) => { + const labelName = label.data.title; + debug( + "Testing label '%s' against regex %s", + labelName, + labelConfig.regex ); + if (labelConfig.regex.test(labelName)) { + debug( + "Setting %s on #%s because of a label reading %s", + labelConfig.name, + self.number, + labelName + ); - if (labelConfig.process) { - self[labelConfig.name] = labelConfig.process(labelName); - } else { - self[labelConfig.name] = labelName; + if (labelConfig.process) { + self[labelConfig.name] = labelConfig.process(labelName); + } else { + self[labelConfig.name] = labelName; + } } - } + }); }); - }); - } else { - log("No labels on %s", self.number); + } else { + debug("No labels on %s", self.number); + } } -}; -/** - * A factory method to create an issue from GitHub data. Currently, the data - * in Issue is almost identical to the data coming from GitHub. - */ -Issue.getFromGH = function (data, labels) { - var issueData = { - repo: data.repo, - number: data.number, - title: data.title, - status: data.state, - date_created: new Date(data.created_at), - date_closed: utils.fromDateString(data.closed_at), - milestone: data.milestone - ? { + /** + * A factory method to create an issue from GitHub data. Currently, the data + * in Issue is almost identical to the data coming from GitHub. + */ + static getFromGH(data, labels) { + const issueData = { + repo: data.repo, + number: data.number, + title: data.title, + status: data.state, + date_created: new Date(data.created_at), + date_closed: utils.fromDateString(data.closed_at), + milestone: data.milestone + ? { title: data.milestone.title, due_on: new Date(data.milestone.due_on), } - : null, - assignee: getLogin(data.assignee), - labels: labels || [], - }; + : null, + assignee: getLogin(data.assignee), + labels: labels || [], + }; - return new Issue(issueData, labels); -}; + return new Issue(issueData, labels); + } -/** - * A factory method to create an issue from a DBIssue. - */ -Issue.getFromDB = function (data, labels) { - var issueData = { - repo: data.repo, - number: data.number, - title: data.title, - status: data.status, - date_created: utils.fromUnixTime(data.date_created), - date_closed: utils.fromUnixTime(data.date_closed), - milestone: data.milestone_title - ? { + /** + * A factory method to create an issue from a DBIssue. + */ + static getFromDB(data, labels) { + const issueData = { + repo: data.repo, + number: data.number, + title: data.title, + status: data.status, + date_created: utils.fromUnixTime(data.date_created), + date_closed: utils.fromUnixTime(data.date_closed), + milestone: data.milestone_title + ? { title: data.milestone_title, due_on: utils.fromUnixTime(data.milestone_due_on), } - : null, - difficulty: data.difficulty, - assignee: data.assignee, - labels: labels || [], - }; - return new Issue(issueData, labels); -}; + : null, + difficulty: data.difficulty, + assignee: data.assignee, + labels: labels || [], + }; + return new Issue(issueData, labels); + } +} -module.exports = Issue; +export default Issue; diff --git a/models/label.js b/models/label.js index 7a857e1f..165911d7 100644 --- a/models/label.js +++ b/models/label.js @@ -1,30 +1,32 @@ -var utils = require("../lib/utils"); +import utils from "../lib/utils.js"; /** * Build a Label object. */ -function Label(data, pullNumber, repoFullName, user, created_at) { - this.data = { - title: data.name, - number: pullNumber, - repo: repoFullName, - user: user, - created_at: utils.fromDateString(created_at), - }; -} +class Label { + constructor(data, pullNumber, repoFullName, user, created_at) { + this.data = { + title: data.name, + number: pullNumber, + repo: repoFullName, + user: user, + created_at: utils.fromDateString(created_at), + }; + } -/** - * Takes an object representing a DB row, and returns an instance of this - * Label object. - */ -Label.getFromDB = function getFromDB(data) { - return new Label( - { name: data.title }, - data.number, - data.repo, - data.user, - utils.fromUnixTime(data.date) - ); -}; + /** + * Takes an object representing a DB row, and returns an instance of this + * Label object. + */ + static getFromDB(data) { + return new Label( + { name: data.title }, + data.number, + data.repo, + data.user, + utils.fromUnixTime(data.date) + ); + } +} -module.exports = Label; +export default Label; diff --git a/models/pull.js b/models/pull.js index 43b736e1..f1602fd7 100644 --- a/models/pull.js +++ b/models/pull.js @@ -1,284 +1,286 @@ -var utils = require("../lib/utils"); -var _ = require("underscore"); -var config = require("../lib/config-loader"); -var queue = require("../lib/pull-queue"); -var Promise = require("bluebird"); -var debug = require("../lib/debug")("pulldasher:pull"); -var DBPull = require("./db_pull"); -var getLogin = require("../lib/get-user-login"); +import utils from "../lib/utils.js"; +import _ from "underscore"; +import config from "../lib/config-loader.js"; +import queue from "../lib/pull-queue.js"; +import Promise from "bluebird"; +import debug from "../lib/debug.js"; +import DBPull from "./db_pull.js"; +import getLogin from "../lib/get-user-login.js"; -function Pull(data, signatures, comments, reviews, commitStatuses, labels) { - this.data = data; - this.signatures = signatures || []; - this.comments = comments || []; - this.reviews = reviews || []; - this.commitStatuses = commitStatuses || []; - this.labels = labels || []; +const log = debug("pulldasher:pull"); - // If github pull-data, parse the body for the cr and qa req... else - // use the values stored in the db. - if (typeof data.cr_req === "undefined") { - var bodyTags = Pull.parseBody(this.data.body); - this.data.cr_req = bodyTags["cr_req"]; - this.data.qa_req = bodyTags["qa_req"]; - this.data.closes = bodyTags["closes"]; - this.data.connects = bodyTags["connects"]; - } else { - this.data.cr_req = data.cr_req; - this.data.qa_req = data.qa_req; - this.data.closes = data.closes; - this.data.connects = data.connects; - } - this.identifySignatures(); -} +class Pull { + constructor(data, signatures, comments, reviews, commitStatuses, labels) { + this.data = data; + this.signatures = signatures || []; + this.comments = comments || []; + this.reviews = reviews || []; + this.commitStatuses = commitStatuses || []; + this.labels = labels || []; -Pull.prototype.update = function () { - debug( - "Calling `updatePull` for pull #%s in repo %s", - this.data.number, - this.data.repo - ); - var dbPull = new DBPull(this); - var number = dbPull.data.number; - var repo = dbPull.data.repo; + // If github pull-data, parse the body for the cr and qa req... else + // use the values stored in the db. + if (typeof data.cr_req === "undefined") { + const bodyTags = Pull.parseBody(this.data.body); + this.data.cr_req = bodyTags["cr_req"]; + this.data.qa_req = bodyTags["qa_req"]; + this.data.closes = bodyTags["closes"]; + this.data.connects = bodyTags["connects"]; + } else { + this.data.cr_req = data.cr_req; + this.data.qa_req = data.qa_req; + this.data.closes = data.closes; + this.data.connects = data.connects; + } + this.identifySignatures(); + } - return dbPull.save().then(function () { - queue.markPullAsDirty(repo, number); - debug("updatePull: Pull #%s updated in repo %s", number, repo); - }); -}; + update() { + log( + "Calling `updatePull` for pull #%s in repo %s", + this.data.number, + this.data.repo + ); + const dbPull = new DBPull(this); + const number = dbPull.data.number; + const repo = dbPull.data.repo; -/** - * Sets sig.data.source_type for each comment, determining where it came from - * by checking for the presence of the comment_id in the list of review ids - * from the DB. - * - * TODO: add a column on signatures table for this value, instead of testing - * for presence in our reviews list. - */ -Pull.prototype.identifySignatures = function () { - const reviewIds = new Set( - this.reviews.map((review) => review.data.review_id) - ); - this.signatures.forEach((sig) => { - sig.data.source_type = reviewIds.has(sig.data.comment_id) - ? "review" - : "comment"; - }); -}; + return dbPull.save().then(() => { + queue.markPullAsDirty(repo, number); + log("updatePull: Pull #%s updated in repo %s", number, repo); + }); + } -Pull.prototype.syncToIssue = function () { - return Promise.resolve(this); - /* The below needs to be rethought a bit and possibly the causal direction - * reversed (updates to the issue should propagate to the pull). - var Issue = require('./issue'); - var self = this; - var connected = this.data.closes || this.data.connects; - if (!this.data.milestone.title && connected) { - return Issue.findByNumber(this.data.repo, connected). - then(function(issue) { - debug("Updating pull from issue: %s", issue.number); - if (issue.milestone) { - var milestone = self.data.milestone; - milestone.title = issue.milestone.title; - milestone.due_on = issue.milestone.due_on; - } - self.data.difficulty = issue.difficulty; - return self.update(); - }). - then(function() { - // This makes it easier to chain a call to this function - return self; - }); - } else { - return new Promise.resolve(self); - } + /** + * Sets sig.data.source_type for each comment, determining where it came from + * by checking for the presence of the comment_id in the list of review ids + * from the DB. + * + * TODO: add a column on signatures table for this value, instead of testing + * for presence in our reviews list. */ -}; - -Pull.prototype.toObject = function () { - var data = _.extend({}, this.data); - data.status = this.getStatus(); - data.labels = this.labels.map(function (label) { - return label.data; - }); - return data; -}; + identifySignatures() { + const reviewIds = new Set( + this.reviews.map((review) => review.data.review_id) + ); + this.signatures.forEach((sig) => { + sig.data.source_type = reviewIds.has(sig.data.comment_id) + ? "review" + : "comment"; + }); + } -/** - * Get all signatures of a given tag. - */ -Pull.prototype.getSignatures = function (tagName) { - return this.getAllSignatures(tagName).filter(function (signature) { - return signature.data.active === 1; - }); -}; + syncToIssue() { + return Promise.resolve(this); + /* The below needs to be rethought a bit and possibly the causal direction + * reversed (updates to the issue should propagate to the pull). + var Issue = require('./issue'); + var self = this; + var connected = this.data.closes || this.data.connects; + if (!this.data.milestone.title && connected) { + return Issue.findByNumber(this.data.repo, connected). + then(function(issue) { + log("Updating pull from issue: %s", issue.number); + if (issue.milestone) { + var milestone = self.data.milestone; + milestone.title = issue.milestone.title; + milestone.due_on = issue.milestone.due_on; + } + self.data.difficulty = issue.difficulty; + return self.update(); + }). + then(function() { + // This makes it easier to chain a call to this function + return self; + }); + } else { + return new Promise.resolve(self); + } + */ + } -Pull.prototype.getAllSignatures = function (tagName) { - return this.signatures.filter(function (signature) { - return signature.data.type === tagName; - }); -}; + toObject() { + var data = _.extend({}, this.data); + data.status = this.getStatus(); + data.labels = this.labels.map((label) => label.data); + return data; + } -Pull.prototype.isOpen = function () { - return this.data.state === "open"; -}; + /** + * Get all signatures of a given tag. + */ + getSignatures(tagName) { + return this.getAllSignatures(tagName).filter((signature) => { + return signature.data.active === 1; + }); + } -/** - * Return an object: - * { - * 'qa_req' : The *needed* number of QA signatures occuring after the last commit - * in order for this pull to be ready for deploy. - * 'cr_req' : The *needed* number of CR signatures occuring after the last commit - * in order for this pull to be ready for deploy. - * 'dev_block' : An array containing the last 'dev_block' signature if the pull is dev blocked, - * or an empty array - * 'deploy_block' : An array containing the last 'deploy_block' signature if pull is deploy blocked, - * or an empty array - * 'commit_statuses' : An array of Status objects - * } - */ -Pull.prototype.getStatus = function getStatus() { - var status = { - qa_req: this.data.qa_req, - cr_req: this.data.cr_req, - allQA: this.getAllSignatures("QA"), - allCR: this.getAllSignatures("CR"), - dev_block: this.getSignatures("dev_block"), - deploy_block: this.getSignatures("deploy_block"), - commit_statuses: this.commitStatuses, - }; + getAllSignatures(tagName) { + return this.signatures.filter((signature) => { + return signature.data.type === tagName; + }); + } - return status; -}; + isOpen() { + return this.data.state === "open"; + } -/** - * Parse body of Pull Request for special tags (e.g. cr_req, qa_req). - */ -Pull.parseBody = function (body) { - var bodyTags = []; + /** + * Return an object: + * { + * 'qa_req' : The *needed* number of QA signatures occuring after the last commit + * in order for this pull to be ready for deploy. + * 'cr_req' : The *needed* number of CR signatures occuring after the last commit + * in order for this pull to be ready for deploy. + * 'dev_block' : An array containing the last 'dev_block' signature if the pull is dev blocked, + * or an empty array + * 'deploy_block' : An array containing the last 'deploy_block' signature if pull is deploy blocked, + * or an empty array + * 'commit_statuses' : An array of Status objects + * } + */ + getStatus() { + var status = { + qa_req: this.data.qa_req, + cr_req: this.data.cr_req, + allQA: this.getAllSignatures("QA"), + allCR: this.getAllSignatures("CR"), + dev_block: this.getSignatures("dev_block"), + deploy_block: this.getSignatures("deploy_block"), + commit_statuses: this.commitStatuses, + }; - config.body_tags.forEach(function (tag) { - var matches = body && body.match(tag.regex); + return status; + } - if (matches) { - bodyTags[tag.name] = matches[1]; - } else { - bodyTags[tag.name] = tag.default; - } - }); + /** + * Parse body of Pull Request for special tags (e.g. cr_req, qa_req). + */ + static parseBody(body) { + var bodyTags = []; - return bodyTags; -}; + config.body_tags.forEach((tag) => { + var matches = body && body.match(tag.regex); -Pull.fromGithubApi = function ( - data, - signatures, - comments, - reviews, - commitStatuses, - labels -) { - data = { - repo: data.base.repo.full_name, - number: data.number, - state: data.state, - title: data.title, - body: data.body || "", - draft: data.draft, - created_at: utils.fromDateString(data.created_at), - updated_at: utils.fromDateString(data.updated_at), - closed_at: utils.fromDateString(data.closed_at), - mergeable: data.mergeable, - merged_at: utils.fromDateString(data.merged_at), - difficulty: data.difficulty, - milestone: { - title: data.milestone && data.milestone.title, - due_on: data.milestone && utils.fromDateString(data.milestone.due_on), - }, - head: { - ref: data.head.ref, - sha: data.head.sha, - repo: { - owner: { - login: data.head.repo.owner.login, - }, - name: data.head.repo.name, - }, - }, - base: { - ref: data.base.ref, - }, - user: { - login: getLogin(data.user), - }, - commits: data.commits, - additions: data.additions, - deletions: data.deletions, - changed_files: data.changed_files, - }; + if (matches) { + bodyTags[tag.name] = matches[1]; + } else { + bodyTags[tag.name] = tag.default; + } + }); - return new Pull(data, signatures, comments, reviews, commitStatuses, labels); -}; + return bodyTags; + } -/** - * Takes an object representing a DB row, and returns an instance of this - * Pull object. - */ -Pull.getFromDB = function ( - data, - signatures, - comments, - reviews, - commitStatuses, - labels -) { - var pullData = { - repo: data.repo, - number: data.number, - state: data.state, - title: data.title, - body: data.body, - draft: data.draft === 1, - created_at: utils.fromUnixTime(data.date), - updated_at: utils.fromUnixTime(data.date_updated), - closed_at: utils.fromUnixTime(data.date_closed), - mergeable: data.mergeable, - merged_at: utils.fromUnixTime(data.date_merged), - difficulty: data.difficulty, - additions: data.additions, - deletions: data.deletions, - milestone: { - title: data.milestone_title, - due_on: utils.fromUnixTime(data.milestone_due_on), - }, - head: { - ref: data.head_branch, - sha: data.head_sha, - repo: { - owner: { - login: data.repo.split("/")[0], + static fromGithubApi( + data, + signatures, + comments, + reviews, + commitStatuses, + labels + ) { + data = { + repo: data.base.repo.full_name, + number: data.number, + state: data.state, + title: data.title, + body: data.body || "", + draft: data.draft, + created_at: utils.fromDateString(data.created_at), + updated_at: utils.fromDateString(data.updated_at), + closed_at: utils.fromDateString(data.closed_at), + mergeable: data.mergeable, + merged_at: utils.fromDateString(data.merged_at), + difficulty: data.difficulty, + milestone: { + title: data.milestone && data.milestone.title, + due_on: data.milestone && utils.fromDateString(data.milestone.due_on), + }, + head: { + ref: data.head.ref, + sha: data.head.sha, + repo: { + owner: { + login: data.head.repo.owner.login, + }, + name: data.head.repo.name, }, }, - }, - base: { - ref: data.base_branch, - }, - user: { - login: data.owner, - }, - cr_req: data.cr_req, - qa_req: data.qa_req, - }; + base: { + ref: data.base.ref, + }, + user: { + login: getLogin(data.user), + }, + commits: data.commits, + additions: data.additions, + deletions: data.deletions, + changed_files: data.changed_files, + }; + + return new Pull(data, signatures, comments, reviews, commitStatuses, labels); + } - return new Pull( - pullData, + /** + * Takes an object representing a DB row, and returns an instance of this + * Pull object. + */ + static getFromDB( + data, signatures, comments, reviews, commitStatuses, labels - ); -}; + ) { + var pullData = { + repo: data.repo, + number: data.number, + state: data.state, + title: data.title, + body: data.body, + draft: data.draft === 1, + created_at: utils.fromUnixTime(data.date), + updated_at: utils.fromUnixTime(data.date_updated), + closed_at: utils.fromUnixTime(data.date_closed), + mergeable: data.mergeable, + merged_at: utils.fromUnixTime(data.date_merged), + difficulty: data.difficulty, + additions: data.additions, + deletions: data.deletions, + milestone: { + title: data.milestone_title, + due_on: utils.fromUnixTime(data.milestone_due_on), + }, + head: { + ref: data.head_branch, + sha: data.head_sha, + repo: { + owner: { + login: data.repo.split("/")[0], + }, + }, + }, + base: { + ref: data.base_branch, + }, + user: { + login: data.owner, + }, + cr_req: data.cr_req, + qa_req: data.qa_req, + }; + + return new Pull( + pullData, + signatures, + comments, + reviews, + commitStatuses, + labels + ); + } +} -module.exports = Pull; +export default Pull; diff --git a/models/review.js b/models/review.js index de5c88b3..446544fc 100644 --- a/models/review.js +++ b/models/review.js @@ -1,39 +1,41 @@ -var utils = require("../lib/utils"); -var getLogin = require("../lib/get-user-login"); +import utils from "../lib/utils.js"; +import getLogin from "../lib/get-user-login.js"; /** * A Pull Request review. */ -function Review(data) { - this.data = { - repo: data.repo, - review_id: data.id, - number: data.number, - body: data.body, - state: data.state, - user: { - login: getLogin(data.user), - }, - submitted_at: new Date(data.submitted_at), - }; -} +class Review { + constructor(data) { + this.data = { + repo: data.repo, + review_id: data.id, + number: data.number, + body: data.body, + state: data.state, + user: { + login: getLogin(data.user), + }, + submitted_at: new Date(data.submitted_at), + }; + } -/** - * Takes an object representing a DB row, and returns an instance of this - * Review object. - */ -Review.getFromDB = function (data) { - return new Review({ - repo: data.repo, - id: data.review_id, - number: data.number, - body: data.body, - state: data.state, - user: { - login: data.user, - }, - submitted_at: utils.fromUnixTime(data.date), - }); -}; + /** + * Takes an object representing a DB row, and returns an instance of this + * Review object. + */ + static getFromDB(data) { + return new Review({ + repo: data.repo, + id: data.review_id, + number: data.number, + body: data.body, + state: data.state, + user: { + login: data.user, + }, + submitted_at: utils.fromUnixTime(data.date), + }); + } +} -module.exports = Review; +export default Review; diff --git a/models/signature.js b/models/signature.js index c5285ba1..d3e58867 100644 --- a/models/signature.js +++ b/models/signature.js @@ -1,7 +1,7 @@ -var config = require("../lib/config-loader"), - getLogin = require("../lib/get-user-login"), - getUserid = require("../lib/get-user-id"), - utils = require("../lib/utils"); +import config from "../lib/config-loader.js"; +import getLogin from "../lib/get-user-login.js"; +import getUserid from "../lib/get-user-id.js"; +import utils from "../lib/utils.js"; /** * A block or signoff in a comment. @@ -113,8 +113,8 @@ Signature.compare = function (a, b) { return Date.parse(a.data.created_at) - Date.parse(b.data.created_at); }; -module.exports = Signature; - function hasTag(body, tag) { return tag.regex.test(body); } + +export default Signature; diff --git a/models/status.js b/models/status.js index 03632a56..093ad191 100644 --- a/models/status.js +++ b/models/status.js @@ -1,36 +1,38 @@ -var utils = require("../lib/utils"); +import utils from "../lib/utils.js"; /** * An object representing the build status of the head commit of a pull. */ -function Status(data) { - this.data = { - repo: data.repo, - sha: data.sha, - target_url: data.target_url, - description: data.description, - state: data.state, - context: data.context, - started_at: utils.toUnixTime(data.started_at), - completed_at: utils.toUnixTime(data.completed_at), - }; -} +class Status { + constructor(data) { + this.data = { + repo: data.repo, + sha: data.sha, + target_url: data.target_url, + description: data.description, + state: data.state, + context: data.context, + started_at: utils.toUnixTime(data.started_at), + completed_at: utils.toUnixTime(data.completed_at), + }; + } -/** - * Takes an object representing a DB row, and returns an object which mimics - * a GitHub API response which may be used to initialize an instance of this - * Status object. - */ -Status.getFromDB = function (data) { - return new Status({ - sha: data.commit, - target_url: data.log_url, - description: data.description, - state: data.state, - context: data.context, - started_at: data.started_at, - completed_at: data.completed_at, - }); -}; + /** + * Takes an object representing a DB row, and returns an object which mimics + * a GitHub API response which may be used to initialize an instance of this + * Status object. + */ + static getFromDB(data) { + return new Status({ + sha: data.commit, + target_url: data.log_url, + description: data.description, + state: data.state, + context: data.context, + started_at: data.started_at, + completed_at: data.completed_at, + }); + } +} -module.exports = Status; +export default Status; diff --git a/package-lock.json b/package-lock.json index ebdafe58..031b389a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,8 +16,8 @@ "@fortawesome/fontawesome-svg-core": "^6.1.1", "@fortawesome/free-solid-svg-icons": "^6.0.0", "@fortawesome/react-fontawesome": "^0.1.17", - "@octokit/plugin-throttling": "^3.4.1", - "@octokit/rest": "^19.0.7", + "@octokit/plugin-throttling": "^9.4.0", + "@octokit/rest": "^21.1.0", "@types/underscore": "^1.10.24", "bluebird": "^3.7.1", "body-parser": "^1.19.0", @@ -2892,259 +2892,173 @@ } }, "node_modules/@octokit/auth-token": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", - "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", - "peer": true, - "dependencies": { - "@octokit/types": "^6.0.3" + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-5.1.2.tgz", + "integrity": "sha512-JcQDsBdg49Yky2w2ld20IHAlwr8d/d8N6NiOXbtuoPCqzbsiJgF633mVUw3x4mo0H5ypataQIX7SFu3yy44Mpw==", + "license": "MIT", + "engines": { + "node": ">= 18" } }, "node_modules/@octokit/core": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz", - "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==", - "peer": true, + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-6.1.4.tgz", + "integrity": "sha512-lAS9k7d6I0MPN+gb9bKDt7X8SdxknYqAMh44S5L+lNqIN2NuV8nvv3g8rPp7MuRxcOpxpUIATWprO0C34a8Qmg==", + "license": "MIT", "dependencies": { - "@octokit/auth-token": "^2.4.4", - "@octokit/graphql": "^4.5.8", - "@octokit/request": "^5.6.3", - "@octokit/request-error": "^2.0.5", - "@octokit/types": "^6.0.3", - "before-after-hook": "^2.2.0", - "universal-user-agent": "^6.0.0" + "@octokit/auth-token": "^5.0.0", + "@octokit/graphql": "^8.1.2", + "@octokit/request": "^9.2.1", + "@octokit/request-error": "^6.1.7", + "@octokit/types": "^13.6.2", + "before-after-hook": "^3.0.2", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 18" } }, "node_modules/@octokit/endpoint": { - "version": "6.0.12", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", - "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", - "peer": true, + "version": "10.1.3", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.3.tgz", + "integrity": "sha512-nBRBMpKPhQUxCsQQeW+rCJ/OPSMcj3g0nfHn01zGYZXuNDvvXudF/TYY6APj5THlurerpFN4a/dQAIAaM6BYhA==", + "license": "MIT", "dependencies": { - "@octokit/types": "^6.0.3", - "is-plain-object": "^5.0.0", - "universal-user-agent": "^6.0.0" + "@octokit/types": "^13.6.2", + "universal-user-agent": "^7.0.2" + }, + "engines": { + "node": ">= 18" } }, "node_modules/@octokit/graphql": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", - "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", - "peer": true, + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-8.2.0.tgz", + "integrity": "sha512-gejfDywEml/45SqbWTWrhfwvLBrcGYhOn50sPOjIeVvH6i7D16/9xcFA8dAJNp2HMcd+g4vru41g4E2RBiZvfQ==", + "license": "MIT", "dependencies": { - "@octokit/request": "^5.6.0", - "@octokit/types": "^6.0.3", - "universal-user-agent": "^6.0.0" + "@octokit/request": "^9.1.4", + "@octokit/types": "^13.8.0", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 18" } }, "node_modules/@octokit/openapi-types": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-11.2.0.tgz", - "integrity": "sha512-PBsVO+15KSlGmiI8QAzaqvsNlZlrDlyAJYcrXBCvVUxCp7VnXjkwPoFHgjEJXx3WF9BAwkA6nfCUA7i9sODzKA==" - }, - "node_modules/@octokit/plugin-request-log": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", - "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", - "peerDependencies": { - "@octokit/core": ">=3" - } - }, - "node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-7.0.1.tgz", - "integrity": "sha512-pnCaLwZBudK5xCdrR823xHGNgqOzRnJ/mpC/76YPpNP7DybdsJtP7mdOwh+wYZxK5jqeQuhu59ogMI4NRlBUvA==", + "version": "23.0.1", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-23.0.1.tgz", + "integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g==", + "license": "MIT" + }, + "node_modules/@octokit/plugin-paginate-rest": { + "version": "11.4.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.4.2.tgz", + "integrity": "sha512-BXJ7XPCTDXFF+wxcg/zscfgw2O/iDPtNSkwwR1W1W5c4Mb3zav/M2XvxQ23nVmKj7jpweB4g8viMeCQdm7LMVA==", + "license": "MIT", "dependencies": { - "@octokit/types": "^9.0.0", - "deprecation": "^2.3.1" + "@octokit/types": "^13.7.0" }, "engines": { - "node": ">= 14" + "node": ">= 18" }, "peerDependencies": { - "@octokit/core": ">=3" - } - }, - "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/openapi-types": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-16.0.0.tgz", - "integrity": "sha512-JbFWOqTJVLHZSUUoF4FzAZKYtqdxWu9Z5m2QQnOyEa04fOFljvyh7D3GYKbfuaSWisqehImiVIMG4eyJeP5VEA==" - }, - "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.0.0.tgz", - "integrity": "sha512-LUewfj94xCMH2rbD5YJ+6AQ4AVjFYTgpp6rboWM5T7N3IsIF65SBEOVcYMGAEzO/kKNiNaW4LoWtoThOhH06gw==", - "dependencies": { - "@octokit/openapi-types": "^16.0.0" + "@octokit/core": ">=6" } }, - "node_modules/@octokit/plugin-throttling": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-3.6.2.tgz", - "integrity": "sha512-0az5fxgVlhFfFtiKLKVXTpmCG2tK3BG0fYI8SO4pmGlN1kyJktJVQA+6KKaFxtxMIWsuHmSEAkR6zSgtk86g2A==", - "dependencies": { - "@octokit/types": "^6.0.1", - "bottleneck": "^2.15.3" + "node_modules/@octokit/plugin-request-log": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-5.3.1.tgz", + "integrity": "sha512-n/lNeCtq+9ofhC15xzmJCNKP2BWTv8Ih2TTy+jatNCCq/gQP/V7rK3fjIfuz0pDWDALO/o/4QY4hyOF6TQQFUw==", + "license": "MIT", + "engines": { + "node": ">= 18" }, "peerDependencies": { - "@octokit/core": "^3.5.0" - } - }, - "node_modules/@octokit/request": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", - "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", - "peer": true, - "dependencies": { - "@octokit/endpoint": "^6.0.1", - "@octokit/request-error": "^2.1.0", - "@octokit/types": "^6.16.1", - "is-plain-object": "^5.0.0", - "node-fetch": "^2.6.7", - "universal-user-agent": "^6.0.0" - } - }, - "node_modules/@octokit/request-error": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", - "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", - "peer": true, - "dependencies": { - "@octokit/types": "^6.0.3", - "deprecation": "^2.0.0", - "once": "^1.4.0" - } - }, - "node_modules/@octokit/rest": { - "version": "19.0.7", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.7.tgz", - "integrity": "sha512-HRtSfjrWmWVNp2uAkEpQnuGMJsu/+dBr47dRc5QVgsCbnIc1+GFEaoKBWkYG+zjrsHpSqcAElMio+n10c0b5JA==", - "dependencies": { - "@octokit/core": "^4.1.0", - "@octokit/plugin-paginate-rest": "^6.0.0", - "@octokit/plugin-request-log": "^1.0.4", - "@octokit/plugin-rest-endpoint-methods": "^7.0.0" - }, - "engines": { - "node": ">= 14" + "@octokit/core": ">=6" } }, - "node_modules/@octokit/rest/node_modules/@octokit/auth-token": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.3.tgz", - "integrity": "sha512-/aFM2M4HVDBT/jjDBa84sJniv1t9Gm/rLkalaz9htOm+L+8JMj1k9w0CkUdcxNyNxZPlTxKPVko+m1VlM58ZVA==", + "node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "13.3.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-13.3.1.tgz", + "integrity": "sha512-o8uOBdsyR+WR8MK9Cco8dCgvG13H1RlM1nWnK/W7TEACQBFux/vPREgKucxUfuDQ5yi1T3hGf4C5ZmZXAERgwQ==", + "license": "MIT", "dependencies": { - "@octokit/types": "^9.0.0" + "@octokit/types": "^13.8.0" }, "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/rest/node_modules/@octokit/core": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.0.tgz", - "integrity": "sha512-AgvDRUg3COpR82P7PBdGZF/NNqGmtMq2NiPqeSsDIeCfYFOZ9gddqWNQHnFdEUf+YwOj4aZYmJnlPp7OXmDIDg==", - "dependencies": { - "@octokit/auth-token": "^3.0.0", - "@octokit/graphql": "^5.0.0", - "@octokit/request": "^6.0.0", - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^9.0.0", - "before-after-hook": "^2.2.0", - "universal-user-agent": "^6.0.0" + "node": ">= 18" }, - "engines": { - "node": ">= 14" + "peerDependencies": { + "@octokit/core": ">=6" } }, - "node_modules/@octokit/rest/node_modules/@octokit/endpoint": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.5.tgz", - "integrity": "sha512-LG4o4HMY1Xoaec87IqQ41TQ+glvIeTKqfjkCEmt5AIwDZJwQeVZFIEYXrYY6yLwK+pAScb9Gj4q+Nz2qSw1roA==", + "node_modules/@octokit/plugin-throttling": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-9.4.0.tgz", + "integrity": "sha512-IOlXxXhZA4Z3m0EEYtrrACkuHiArHLZ3CvqWwOez/pURNqRuwfoFlTPbN5Muf28pzFuztxPyiUiNwz8KctdZaQ==", + "license": "MIT", "dependencies": { - "@octokit/types": "^9.0.0", - "is-plain-object": "^5.0.0", - "universal-user-agent": "^6.0.0" + "@octokit/types": "^13.7.0", + "bottleneck": "^2.15.3" }, "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/rest/node_modules/@octokit/graphql": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.5.tgz", - "integrity": "sha512-Qwfvh3xdqKtIznjX9lz2D458r7dJPP8l6r4GQkIdWQouZwHQK0mVT88uwiU2bdTU2OtT1uOlKpRciUWldpG0yQ==", - "dependencies": { - "@octokit/request": "^6.0.0", - "@octokit/types": "^9.0.0", - "universal-user-agent": "^6.0.0" + "node": ">= 18" }, - "engines": { - "node": ">= 14" + "peerDependencies": { + "@octokit/core": "^6.1.3" } }, - "node_modules/@octokit/rest/node_modules/@octokit/openapi-types": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-16.0.0.tgz", - "integrity": "sha512-JbFWOqTJVLHZSUUoF4FzAZKYtqdxWu9Z5m2QQnOyEa04fOFljvyh7D3GYKbfuaSWisqehImiVIMG4eyJeP5VEA==" - }, - "node_modules/@octokit/rest/node_modules/@octokit/plugin-paginate-rest": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.0.0.tgz", - "integrity": "sha512-Sq5VU1PfT6/JyuXPyt04KZNVsFOSBaYOAq2QRZUwzVlI10KFvcbUo8lR258AAQL1Et60b0WuVik+zOWKLuDZxw==", + "node_modules/@octokit/request": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.2.1.tgz", + "integrity": "sha512-TqHLIdw1KFvx8WvLc7Jv94r3C3+AzKY2FWq7c20zvrxmCIa6MCVkLCE/826NCXnml3LFJjLsidDh1BhMaGEDQw==", + "license": "MIT", "dependencies": { - "@octokit/types": "^9.0.0" + "@octokit/endpoint": "^10.1.3", + "@octokit/request-error": "^6.1.6", + "@octokit/types": "^13.6.2", + "fast-content-type-parse": "^2.0.0", + "universal-user-agent": "^7.0.2" }, "engines": { - "node": ">= 14" - }, - "peerDependencies": { - "@octokit/core": ">=4" + "node": ">= 18" } }, - "node_modules/@octokit/rest/node_modules/@octokit/request": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.3.tgz", - "integrity": "sha512-TNAodj5yNzrrZ/VxP+H5HiYaZep0H3GU0O7PaF+fhDrt8FPrnkei9Aal/txsN/1P7V3CPiThG0tIvpPDYUsyAA==", + "node_modules/@octokit/request-error": { + "version": "6.1.7", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.7.tgz", + "integrity": "sha512-69NIppAwaauwZv6aOzb+VVLwt+0havz9GT5YplkeJv7fG7a40qpLt/yZKyiDxAhgz0EtgNdNcb96Z0u+Zyuy2g==", + "license": "MIT", "dependencies": { - "@octokit/endpoint": "^7.0.0", - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^9.0.0", - "is-plain-object": "^5.0.0", - "node-fetch": "^2.6.7", - "universal-user-agent": "^6.0.0" + "@octokit/types": "^13.6.2" }, "engines": { - "node": ">= 14" + "node": ">= 18" } }, - "node_modules/@octokit/rest/node_modules/@octokit/request-error": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.3.tgz", - "integrity": "sha512-crqw3V5Iy2uOU5Np+8M/YexTlT8zxCfI+qu+LxUB7SZpje4Qmx3mub5DfEKSO8Ylyk0aogi6TYdf6kxzh2BguQ==", + "node_modules/@octokit/rest": { + "version": "21.1.0", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-21.1.0.tgz", + "integrity": "sha512-93iLxcKDJboUpmnUyeJ6cRIi7z7cqTZT1K7kRK4LobGxwTwpsa+2tQQbRQNGy7IFDEAmrtkf4F4wBj3D5rVlJQ==", + "license": "MIT", "dependencies": { - "@octokit/types": "^9.0.0", - "deprecation": "^2.0.0", - "once": "^1.4.0" + "@octokit/core": "^6.1.3", + "@octokit/plugin-paginate-rest": "^11.4.0", + "@octokit/plugin-request-log": "^5.3.1", + "@octokit/plugin-rest-endpoint-methods": "^13.3.0" }, "engines": { - "node": ">= 14" - } - }, - "node_modules/@octokit/rest/node_modules/@octokit/types": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.0.0.tgz", - "integrity": "sha512-LUewfj94xCMH2rbD5YJ+6AQ4AVjFYTgpp6rboWM5T7N3IsIF65SBEOVcYMGAEzO/kKNiNaW4LoWtoThOhH06gw==", - "dependencies": { - "@octokit/openapi-types": "^16.0.0" + "node": ">= 18" } }, "node_modules/@octokit/types": { - "version": "6.34.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.34.0.tgz", - "integrity": "sha512-s1zLBjWhdEI2zwaoSgyOFoKSl109CUcVBCc7biPJ3aAf6LGLU6szDvi31JPU7bxfla2lqfhjbbg/5DdFNxOwHw==", + "version": "13.8.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.8.0.tgz", + "integrity": "sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==", + "license": "MIT", "dependencies": { - "@octokit/openapi-types": "^11.2.0" + "@octokit/openapi-types": "^23.0.1" } }, "node_modules/@popperjs/core": { @@ -4263,9 +4177,10 @@ "dev": true }, "node_modules/before-after-hook": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.2.tgz", - "integrity": "sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ==" + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-3.0.2.tgz", + "integrity": "sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A==", + "license": "Apache-2.0" }, "node_modules/big.js": { "version": "5.2.2", @@ -5068,11 +4983,6 @@ "node": ">= 0.8" } }, - "node_modules/deprecation": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", - "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" - }, "node_modules/destroy": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", @@ -6151,6 +6061,22 @@ "node": ">= 0.8" } }, + "node_modules/fast-content-type-parse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-2.0.1.tgz", + "integrity": "sha512-nGqtvLrj5w0naR6tDPfB4cUmYCqouzyQiz6C5y/LtcDllJdrcc6WaWW6iXyIIOErTa/XRybj28aasdn4LkVk6Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -7249,14 +7175,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-property": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", @@ -8294,25 +8212,6 @@ "tslib": "^2.0.3" } }, - "node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, "node_modules/node-forge": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", @@ -8506,6 +8405,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, "dependencies": { "wrappy": "1" } @@ -10507,11 +10407,6 @@ "node": ">=0.6" } }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" - }, "node_modules/ts-loader": { "version": "9.2.8", "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.2.8.tgz", @@ -10792,9 +10687,10 @@ } }, "node_modules/universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.2.tgz", + "integrity": "sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q==", + "license": "ISC" }, "node_modules/unpipe": { "version": "1.0.0", @@ -10952,11 +10848,6 @@ "minimalistic-assert": "^1.0.0" } }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" - }, "node_modules/webpack": { "version": "5.94.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz", @@ -11307,15 +11198,6 @@ "node": ">=0.8.0" } }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -11444,7 +11326,8 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true }, "node_modules/ws": { "version": "8.11.0", @@ -13496,225 +13379,116 @@ } }, "@octokit/auth-token": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", - "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", - "peer": true, - "requires": { - "@octokit/types": "^6.0.3" - } + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-5.1.2.tgz", + "integrity": "sha512-JcQDsBdg49Yky2w2ld20IHAlwr8d/d8N6NiOXbtuoPCqzbsiJgF633mVUw3x4mo0H5ypataQIX7SFu3yy44Mpw==" }, "@octokit/core": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz", - "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==", - "peer": true, + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-6.1.4.tgz", + "integrity": "sha512-lAS9k7d6I0MPN+gb9bKDt7X8SdxknYqAMh44S5L+lNqIN2NuV8nvv3g8rPp7MuRxcOpxpUIATWprO0C34a8Qmg==", "requires": { - "@octokit/auth-token": "^2.4.4", - "@octokit/graphql": "^4.5.8", - "@octokit/request": "^5.6.3", - "@octokit/request-error": "^2.0.5", - "@octokit/types": "^6.0.3", - "before-after-hook": "^2.2.0", - "universal-user-agent": "^6.0.0" + "@octokit/auth-token": "^5.0.0", + "@octokit/graphql": "^8.1.2", + "@octokit/request": "^9.2.1", + "@octokit/request-error": "^6.1.7", + "@octokit/types": "^13.6.2", + "before-after-hook": "^3.0.2", + "universal-user-agent": "^7.0.0" } }, "@octokit/endpoint": { - "version": "6.0.12", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", - "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", - "peer": true, + "version": "10.1.3", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.3.tgz", + "integrity": "sha512-nBRBMpKPhQUxCsQQeW+rCJ/OPSMcj3g0nfHn01zGYZXuNDvvXudF/TYY6APj5THlurerpFN4a/dQAIAaM6BYhA==", "requires": { - "@octokit/types": "^6.0.3", - "is-plain-object": "^5.0.0", - "universal-user-agent": "^6.0.0" + "@octokit/types": "^13.6.2", + "universal-user-agent": "^7.0.2" } }, "@octokit/graphql": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", - "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", - "peer": true, + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-8.2.0.tgz", + "integrity": "sha512-gejfDywEml/45SqbWTWrhfwvLBrcGYhOn50sPOjIeVvH6i7D16/9xcFA8dAJNp2HMcd+g4vru41g4E2RBiZvfQ==", "requires": { - "@octokit/request": "^5.6.0", - "@octokit/types": "^6.0.3", - "universal-user-agent": "^6.0.0" + "@octokit/request": "^9.1.4", + "@octokit/types": "^13.8.0", + "universal-user-agent": "^7.0.0" } }, "@octokit/openapi-types": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-11.2.0.tgz", - "integrity": "sha512-PBsVO+15KSlGmiI8QAzaqvsNlZlrDlyAJYcrXBCvVUxCp7VnXjkwPoFHgjEJXx3WF9BAwkA6nfCUA7i9sODzKA==" + "version": "23.0.1", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-23.0.1.tgz", + "integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g==" + }, + "@octokit/plugin-paginate-rest": { + "version": "11.4.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.4.2.tgz", + "integrity": "sha512-BXJ7XPCTDXFF+wxcg/zscfgw2O/iDPtNSkwwR1W1W5c4Mb3zav/M2XvxQ23nVmKj7jpweB4g8viMeCQdm7LMVA==", + "requires": { + "@octokit/types": "^13.7.0" + } }, "@octokit/plugin-request-log": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", - "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-5.3.1.tgz", + "integrity": "sha512-n/lNeCtq+9ofhC15xzmJCNKP2BWTv8Ih2TTy+jatNCCq/gQP/V7rK3fjIfuz0pDWDALO/o/4QY4hyOF6TQQFUw==", "requires": {} }, "@octokit/plugin-rest-endpoint-methods": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-7.0.1.tgz", - "integrity": "sha512-pnCaLwZBudK5xCdrR823xHGNgqOzRnJ/mpC/76YPpNP7DybdsJtP7mdOwh+wYZxK5jqeQuhu59ogMI4NRlBUvA==", + "version": "13.3.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-13.3.1.tgz", + "integrity": "sha512-o8uOBdsyR+WR8MK9Cco8dCgvG13H1RlM1nWnK/W7TEACQBFux/vPREgKucxUfuDQ5yi1T3hGf4C5ZmZXAERgwQ==", "requires": { - "@octokit/types": "^9.0.0", - "deprecation": "^2.3.1" - }, - "dependencies": { - "@octokit/openapi-types": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-16.0.0.tgz", - "integrity": "sha512-JbFWOqTJVLHZSUUoF4FzAZKYtqdxWu9Z5m2QQnOyEa04fOFljvyh7D3GYKbfuaSWisqehImiVIMG4eyJeP5VEA==" - }, - "@octokit/types": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.0.0.tgz", - "integrity": "sha512-LUewfj94xCMH2rbD5YJ+6AQ4AVjFYTgpp6rboWM5T7N3IsIF65SBEOVcYMGAEzO/kKNiNaW4LoWtoThOhH06gw==", - "requires": { - "@octokit/openapi-types": "^16.0.0" - } - } + "@octokit/types": "^13.8.0" } }, "@octokit/plugin-throttling": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-3.6.2.tgz", - "integrity": "sha512-0az5fxgVlhFfFtiKLKVXTpmCG2tK3BG0fYI8SO4pmGlN1kyJktJVQA+6KKaFxtxMIWsuHmSEAkR6zSgtk86g2A==", + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-9.4.0.tgz", + "integrity": "sha512-IOlXxXhZA4Z3m0EEYtrrACkuHiArHLZ3CvqWwOez/pURNqRuwfoFlTPbN5Muf28pzFuztxPyiUiNwz8KctdZaQ==", "requires": { - "@octokit/types": "^6.0.1", + "@octokit/types": "^13.7.0", "bottleneck": "^2.15.3" } }, "@octokit/request": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", - "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", - "peer": true, + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.2.1.tgz", + "integrity": "sha512-TqHLIdw1KFvx8WvLc7Jv94r3C3+AzKY2FWq7c20zvrxmCIa6MCVkLCE/826NCXnml3LFJjLsidDh1BhMaGEDQw==", "requires": { - "@octokit/endpoint": "^6.0.1", - "@octokit/request-error": "^2.1.0", - "@octokit/types": "^6.16.1", - "is-plain-object": "^5.0.0", - "node-fetch": "^2.6.7", - "universal-user-agent": "^6.0.0" + "@octokit/endpoint": "^10.1.3", + "@octokit/request-error": "^6.1.6", + "@octokit/types": "^13.6.2", + "fast-content-type-parse": "^2.0.0", + "universal-user-agent": "^7.0.2" } }, "@octokit/request-error": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", - "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", - "peer": true, + "version": "6.1.7", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.7.tgz", + "integrity": "sha512-69NIppAwaauwZv6aOzb+VVLwt+0havz9GT5YplkeJv7fG7a40qpLt/yZKyiDxAhgz0EtgNdNcb96Z0u+Zyuy2g==", "requires": { - "@octokit/types": "^6.0.3", - "deprecation": "^2.0.0", - "once": "^1.4.0" + "@octokit/types": "^13.6.2" } }, "@octokit/rest": { - "version": "19.0.7", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.7.tgz", - "integrity": "sha512-HRtSfjrWmWVNp2uAkEpQnuGMJsu/+dBr47dRc5QVgsCbnIc1+GFEaoKBWkYG+zjrsHpSqcAElMio+n10c0b5JA==", + "version": "21.1.0", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-21.1.0.tgz", + "integrity": "sha512-93iLxcKDJboUpmnUyeJ6cRIi7z7cqTZT1K7kRK4LobGxwTwpsa+2tQQbRQNGy7IFDEAmrtkf4F4wBj3D5rVlJQ==", "requires": { - "@octokit/core": "^4.1.0", - "@octokit/plugin-paginate-rest": "^6.0.0", - "@octokit/plugin-request-log": "^1.0.4", - "@octokit/plugin-rest-endpoint-methods": "^7.0.0" - }, - "dependencies": { - "@octokit/auth-token": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.3.tgz", - "integrity": "sha512-/aFM2M4HVDBT/jjDBa84sJniv1t9Gm/rLkalaz9htOm+L+8JMj1k9w0CkUdcxNyNxZPlTxKPVko+m1VlM58ZVA==", - "requires": { - "@octokit/types": "^9.0.0" - } - }, - "@octokit/core": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.0.tgz", - "integrity": "sha512-AgvDRUg3COpR82P7PBdGZF/NNqGmtMq2NiPqeSsDIeCfYFOZ9gddqWNQHnFdEUf+YwOj4aZYmJnlPp7OXmDIDg==", - "requires": { - "@octokit/auth-token": "^3.0.0", - "@octokit/graphql": "^5.0.0", - "@octokit/request": "^6.0.0", - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^9.0.0", - "before-after-hook": "^2.2.0", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/endpoint": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.5.tgz", - "integrity": "sha512-LG4o4HMY1Xoaec87IqQ41TQ+glvIeTKqfjkCEmt5AIwDZJwQeVZFIEYXrYY6yLwK+pAScb9Gj4q+Nz2qSw1roA==", - "requires": { - "@octokit/types": "^9.0.0", - "is-plain-object": "^5.0.0", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/graphql": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.5.tgz", - "integrity": "sha512-Qwfvh3xdqKtIznjX9lz2D458r7dJPP8l6r4GQkIdWQouZwHQK0mVT88uwiU2bdTU2OtT1uOlKpRciUWldpG0yQ==", - "requires": { - "@octokit/request": "^6.0.0", - "@octokit/types": "^9.0.0", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/openapi-types": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-16.0.0.tgz", - "integrity": "sha512-JbFWOqTJVLHZSUUoF4FzAZKYtqdxWu9Z5m2QQnOyEa04fOFljvyh7D3GYKbfuaSWisqehImiVIMG4eyJeP5VEA==" - }, - "@octokit/plugin-paginate-rest": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.0.0.tgz", - "integrity": "sha512-Sq5VU1PfT6/JyuXPyt04KZNVsFOSBaYOAq2QRZUwzVlI10KFvcbUo8lR258AAQL1Et60b0WuVik+zOWKLuDZxw==", - "requires": { - "@octokit/types": "^9.0.0" - } - }, - "@octokit/request": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.3.tgz", - "integrity": "sha512-TNAodj5yNzrrZ/VxP+H5HiYaZep0H3GU0O7PaF+fhDrt8FPrnkei9Aal/txsN/1P7V3CPiThG0tIvpPDYUsyAA==", - "requires": { - "@octokit/endpoint": "^7.0.0", - "@octokit/request-error": "^3.0.0", - "@octokit/types": "^9.0.0", - "is-plain-object": "^5.0.0", - "node-fetch": "^2.6.7", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/request-error": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-3.0.3.tgz", - "integrity": "sha512-crqw3V5Iy2uOU5Np+8M/YexTlT8zxCfI+qu+LxUB7SZpje4Qmx3mub5DfEKSO8Ylyk0aogi6TYdf6kxzh2BguQ==", - "requires": { - "@octokit/types": "^9.0.0", - "deprecation": "^2.0.0", - "once": "^1.4.0" - } - }, - "@octokit/types": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.0.0.tgz", - "integrity": "sha512-LUewfj94xCMH2rbD5YJ+6AQ4AVjFYTgpp6rboWM5T7N3IsIF65SBEOVcYMGAEzO/kKNiNaW4LoWtoThOhH06gw==", - "requires": { - "@octokit/openapi-types": "^16.0.0" - } - } + "@octokit/core": "^6.1.3", + "@octokit/plugin-paginate-rest": "^11.4.0", + "@octokit/plugin-request-log": "^5.3.1", + "@octokit/plugin-rest-endpoint-methods": "^13.3.0" } }, "@octokit/types": { - "version": "6.34.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.34.0.tgz", - "integrity": "sha512-s1zLBjWhdEI2zwaoSgyOFoKSl109CUcVBCc7biPJ3aAf6LGLU6szDvi31JPU7bxfla2lqfhjbbg/5DdFNxOwHw==", + "version": "13.8.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.8.0.tgz", + "integrity": "sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==", "requires": { - "@octokit/openapi-types": "^11.2.0" + "@octokit/openapi-types": "^23.0.1" } }, "@popperjs/core": { @@ -14604,9 +14378,9 @@ "dev": true }, "before-after-hook": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.2.tgz", - "integrity": "sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ==" + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-3.0.2.tgz", + "integrity": "sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A==" }, "big.js": { "version": "5.2.2", @@ -15206,11 +14980,6 @@ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" }, - "deprecation": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", - "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" - }, "destroy": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", @@ -16018,6 +15787,11 @@ } } }, + "fast-content-type-parse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-2.0.1.tgz", + "integrity": "sha512-nGqtvLrj5w0naR6tDPfB4cUmYCqouzyQiz6C5y/LtcDllJdrcc6WaWW6iXyIIOErTa/XRybj28aasdn4LkVk6Q==" + }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -16800,11 +16574,6 @@ "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", "dev": true }, - "is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==" - }, "is-property": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", @@ -17573,14 +17342,6 @@ "tslib": "^2.0.3" } }, - "node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "requires": { - "whatwg-url": "^5.0.0" - } - }, "node-forge": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", @@ -17720,6 +17481,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, "requires": { "wrappy": "1" } @@ -19202,11 +18964,6 @@ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" - }, "ts-loader": { "version": "9.2.8", "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.2.8.tgz", @@ -19413,9 +19170,9 @@ "dev": true }, "universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.2.tgz", + "integrity": "sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q==" }, "unpipe": { "version": "1.0.0", @@ -19523,11 +19280,6 @@ "minimalistic-assert": "^1.0.0" } }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" - }, "webpack": { "version": "5.94.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz", @@ -19771,15 +19523,6 @@ "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", "dev": true }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -19877,7 +19620,8 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true }, "ws": { "version": "8.11.0", diff --git a/package.json b/package.json index aefc867a..db938f12 100644 --- a/package.json +++ b/package.json @@ -9,8 +9,8 @@ "@fortawesome/fontawesome-svg-core": "^6.1.1", "@fortawesome/free-solid-svg-icons": "^6.0.0", "@fortawesome/react-fontawesome": "^0.1.17", - "@octokit/plugin-throttling": "^3.4.1", - "@octokit/rest": "^19.0.7", + "@octokit/plugin-throttling": "^9.4.0", + "@octokit/rest": "^21.1.0", "@types/underscore": "^1.10.24", "bluebird": "^3.7.1", "body-parser": "^1.19.0", @@ -79,5 +79,6 @@ "main": "app.js", "repository": "git@github.com:ifixit/pulldasher.git", "author": "iFixit", - "license": "MIT" -} + "license": "MIT", + "type": "module" +} \ No newline at end of file