Set up CI with ESLint linter and Mocha test runner (#661)

This commit is contained in:
Thomas Durieux
2026-04-15 04:34:03 +02:00
committed by GitHub
parent 812f8b6314
commit f3641c8ce3
14 changed files with 1991 additions and 38 deletions
+32
View File
@@ -0,0 +1,32 @@
name: CI
on:
push:
branches: [master]
pull_request:
branches: [master]
jobs:
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- run: npm run lint
test:
name: Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- run: npm test
+36
View File
@@ -0,0 +1,36 @@
import eslint from "@eslint/js";
import tseslint from "typescript-eslint";
export default tseslint.config(
eslint.configs.recommended,
...tseslint.configs.recommended,
{
ignores: ["build/", "public/", "gulpfile.js", "healthcheck.js", "opentelemetry.js"],
},
{
rules: {
"@typescript-eslint/no-explicit-any": "warn",
"@typescript-eslint/no-unused-vars": [
"warn",
{ argsIgnorePattern: "^_", varsIgnorePattern: "^_" },
],
"@typescript-eslint/no-require-imports": "off",
"@typescript-eslint/no-empty-object-type": "off",
"no-empty": "warn",
},
},
{
files: ["test/**/*.js"],
languageOptions: {
sourceType: "commonjs",
globals: {
describe: "readonly",
it: "readonly",
before: "readonly",
after: "readonly",
beforeEach: "readonly",
afterEach: "readonly",
},
},
}
);
+1905 -25
View File
File diff suppressed because it is too large Load Diff
+5 -1
View File
@@ -7,6 +7,7 @@
},
"scripts": {
"test": "mocha --reporter spec",
"lint": "eslint .",
"start": "node --inspect=5858 -r ts-node/register ./src/server/index.ts",
"dev": "nodemon --transpile-only ./src/server/index.ts",
"build": "rm -rf build && tsc && gulp",
@@ -73,6 +74,7 @@
"unzip-stream": "^0.3.1"
},
"devDependencies": {
"@eslint/js": "^10.0.1",
"@types/archiver": "^5.3.4",
"@types/compression": "^1.7.5",
"@types/crypto-js": "^4.2.2",
@@ -88,6 +90,7 @@
"@types/passport-github2": "^1.2.9",
"@types/unzip-stream": "^0.3.4",
"chai": "^4.5.0",
"eslint": "^10.2.0",
"gulp": "^5.0.0",
"gulp-clean-css": "^4.3.0",
"gulp-concat": "^2.6.1",
@@ -97,7 +100,8 @@
"mocha": "^10.4.0",
"nodemon": "^3.1.0",
"ts-node": "^10.9.2",
"typescript": "^5.4.3"
"typescript": "^5.4.3",
"typescript-eslint": "^8.58.2"
},
"nodemonConfig": {
"ignore": [
+1 -1
View File
@@ -79,7 +79,7 @@ const config: Config = {
S3_REGION: null,
};
for (let conf in process.env) {
for (const conf in process.env) {
if ((config as any)[conf] !== undefined) {
(config as any)[conf] = process.env[conf];
}
+1
View File
@@ -281,6 +281,7 @@ export default class AnonymizedFile {
.startActiveSpan("AnonymizedFile.send", async (span) => {
span.setAttribute("repoId", this.repository.repoId);
span.setAttribute("anonymizedPath", this.anonymizedPath);
// eslint-disable-next-line no-async-promise-executor
return new Promise<void>(async (resolve, reject) => {
try {
if (config.STREAMER_ENTRYPOINT) {
+2 -2
View File
@@ -135,7 +135,7 @@ export default class User {
}).exec()
).map((d) => new Repository(d));
const promises = [];
for (let repo of repositories) {
for (const repo of repositories) {
if (
repo.status == "ready" &&
repo.options.expirationMode != "never" &&
@@ -163,7 +163,7 @@ export default class User {
}).exec()
).map((d) => new PullRequest(d));
const promises = [];
for (let repo of pullRequests) {
for (const repo of pullRequests) {
if (
repo.status == "ready" &&
repo.options.expirationMode != "never" &&
+1 -1
View File
@@ -96,7 +96,7 @@ export class ContentAnonimizer {
}
// remove image in markdown
return content.replace(
/!\[[^\]]*\]\((?<filename>.*?)(?=\"|\))(?<optionalpart>\".*\")?\)/g,
/!\[[^\]]*\]\((?<filename>.*?)(?="|\))(?<optionalpart>".*")?\)/g,
() => {
this.wasAnonymized = true;
return config.ANONYMIZATION_MASK;
+1 -1
View File
@@ -106,7 +106,7 @@ export default class GitHubStream extends GitHubBase {
span.setAttribute("file", file.anonymizedPath);
try {
try {
file.filePath;
void file.filePath;
} catch (_) {
// compute the original path if ambiguous
await file.originalPath();
+3 -3
View File
@@ -145,10 +145,10 @@ export default class FileSystem extends StorageBase {
.startActiveSpan("fs.listFiles", async (span) => {
span.setAttribute("path", dir);
const fullPath = join(config.FOLDER, this.repoPath(repoId), dir);
let files = await fs.promises.readdir(fullPath);
const files = await fs.promises.readdir(fullPath);
const output2: IFile[] = [];
for (let file of files) {
let filePath = join(fullPath, file);
for (const file of files) {
const filePath = join(fullPath, file);
try {
const stats = await fs.promises.stat(filePath);
if (stats.isDirectory()) {
+1 -1
View File
@@ -126,7 +126,7 @@ router.get("/repos", async (req, res) => {
sort = {};
sort[req.query.sort as string] = -1;
}
let query = [];
const query = [];
if (req.query.search) {
query.push({ repoId: { $regex: req.query.search } });
}
+1 -1
View File
@@ -99,7 +99,7 @@ router.get(
);
function validateNewPullRequest(pullRequestUpdate: any): void {
const validCharacters = /^[0-9a-zA-Z\-\_]+$/;
const validCharacters = /^[0-9a-zA-Z\-_]+$/;
if (
!pullRequestUpdate.pullRequestId.match(validCharacters) ||
pullRequestUpdate.pullRequestId.length < 3
+1 -1
View File
@@ -281,7 +281,7 @@ router.get("/:repoId/", async (req: express.Request, res: express.Response) => {
});
function validateNewRepo(repoUpdate: any): void {
const validCharacters = /^[0-9a-zA-Z\-\_]+$/;
const validCharacters = /^[0-9a-zA-Z\-_]+$/;
if (
!repoUpdate.repoId.match(validCharacters) ||
repoUpdate.repoId.length < 3
+1 -1
View File
@@ -85,7 +85,7 @@ function printError(error: any, req?: express.Request) {
}
console.error(message);
} else if (error instanceof HTTPError) {
let message = `[ERROR] HTTP.${
const message = `[ERROR] HTTP.${
error.code
} ${error.message.toString()} ${error.stack?.split("\n")[1].trim()}`;
console.error(message);