mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-17 09:36:08 +08:00
ci: add test & benchmark
This commit is contained in:
1 parent
5c1217dc60
commit
d589217a75
20 files changed
+155
-52
No files matched your search
@@ -45,10 +45,18 @@ jobs:
|
||||
- name: Build And Lint
|
||||
run: |
|
||||
yarn build:ui:gulp
|
||||
parallel --tty -j+0 yarn ::: lint:ci lint:ui:ci build build:ui:production:webpack
|
||||
parallel --tty -j+0 yarn ::: lint:ci lint:ui:ci build build:ui:production:webpack test
|
||||
- name: Publish
|
||||
if: ${{ github.event_name == 'push' }}
|
||||
run: node build/publish.js
|
||||
- name: Benchmark
|
||||
run: yarn benchmark
|
||||
- name: Benchmark result
|
||||
uses: benchmark-action/github-action-benchmark@v1
|
||||
with:
|
||||
name: Benchmark
|
||||
tool: customBiggerIsBetter
|
||||
output-file-path: benchmark.json
|
||||
# web:
|
||||
# needs: build
|
||||
# permissions:
|
||||
|
||||
@@ -11,6 +11,7 @@ dist/
|
||||
*.tsbuildinfo
|
||||
*.hydro
|
||||
.coverage
|
||||
benchmark.json
|
||||
globalConfig.json
|
||||
*.out
|
||||
.clinic/
|
||||
|
||||
+12
-3
@@ -14,6 +14,8 @@
|
||||
"build:ui:dev": "yarn build:ui:gulp && node --trace-deprecation packages/ui-default/build --dev",
|
||||
"build:ui:production": "yarn build:ui:gulp && node packages/ui-default/build --production",
|
||||
"build:ui:production:webpack": "node packages/ui-default/build --production",
|
||||
"test": "mocha",
|
||||
"benchmark": "cross-env BENCHMARK=true mocha",
|
||||
"lint": "eslint packages --ext ts --fix",
|
||||
"lint:ci": "eslint packages --ext ts",
|
||||
"lint:ui": "yarn workspace @hydrooj/ui-default eslint --ext .js,.ts,.jsx,.tsx . --fix",
|
||||
@@ -28,30 +30,37 @@
|
||||
"version": "1.0.0",
|
||||
"license": "AGPL-3.0-only",
|
||||
"devDependencies": {
|
||||
"@types/autocannon": "^7.6.1",
|
||||
"@types/cross-spawn": "^6.0.2",
|
||||
"@types/node": "^17.0.21",
|
||||
"@types/node": "^17.0.23",
|
||||
"@types/semver": "^7.3.9",
|
||||
"@types/supertest": "^2.0.12",
|
||||
"@typescript-eslint/eslint-plugin": "5.14.0",
|
||||
"@typescript-eslint/parser": "5.14.0",
|
||||
"autocannon": "^7.8.1",
|
||||
"cac": "^6.7.12",
|
||||
"cross-env": "^7.0.3",
|
||||
"cross-spawn": "^7.0.3",
|
||||
"esbuild": "0.14.3",
|
||||
"eslint": "^8.11.0",
|
||||
"eslint": "^8.12.0",
|
||||
"eslint-config-airbnb": "^19.0.4",
|
||||
"eslint-config-airbnb-typescript": "16.1.1",
|
||||
"eslint-import-resolver-typescript": "2.5.0",
|
||||
"eslint-import-resolver-webpack": "^0.13.2",
|
||||
"eslint-plugin-import": "2.25.4",
|
||||
"eslint-plugin-jsx-a11y": "^6.5.1",
|
||||
"eslint-plugin-react": "^7.29.3",
|
||||
"eslint-plugin-react": "^7.29.4",
|
||||
"eslint-plugin-simple-import-sort": "7.0.0",
|
||||
"fs-extra": "^10.0.1",
|
||||
"globby": "11.1.0",
|
||||
"latest-version": "^6.0.0",
|
||||
"mocha": "^9.2.2",
|
||||
"mongo-mock": "^4.1.0",
|
||||
"mongodb": "^3.7.3",
|
||||
"mongodb-memory-server": "^8.4.2",
|
||||
"ora": "5.4.1",
|
||||
"semver": "^7.3.5",
|
||||
"supertest": "^6.2.2",
|
||||
"typedoc": "^0.22.13",
|
||||
"typescript": "4.6.2"
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"preferUnplugged": true,
|
||||
"dependencies": {
|
||||
"js-yaml": "^4.1.0",
|
||||
"superagent": "^7.1.1"
|
||||
"superagent": "^7.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/js-yaml": "^4.0.5"
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"author": "undefined <i@undefined.moe>",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"maxmind": "^4.3.5"
|
||||
"maxmind": "^4.3.6"
|
||||
},
|
||||
"preferUnplugged": true,
|
||||
"scripts": {
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
"devDependencies": {
|
||||
"@types/fs-extra": "^9.0.13",
|
||||
"@types/js-yaml": "^4.0.5",
|
||||
"@types/lodash": "^4.14.179",
|
||||
"@types/lodash": "^4.14.181",
|
||||
"@types/shell-quote": "^1.7.1",
|
||||
"@types/ws": "^8.5.3"
|
||||
},
|
||||
|
||||
@@ -12,20 +12,20 @@
|
||||
},
|
||||
"preferUnplugged": true,
|
||||
"dependencies": {
|
||||
"@graphql-tools/schema": "^8.3.2",
|
||||
"@graphql-tools/schema": "^8.3.6",
|
||||
"@hydrooj/utils": "workspace:*",
|
||||
"adm-zip": "0.5.5",
|
||||
"ajv": "^8.10.0",
|
||||
"ajv": "^8.11.0",
|
||||
"ansi_up": "^5.1.0",
|
||||
"cac": "^6.7.12",
|
||||
"cookies": "^0.8.0",
|
||||
"detect-browser": "^5.3.0",
|
||||
"emoji-regex": "^10.0.1",
|
||||
"emoji-regex": "^10.1.0",
|
||||
"emojis-list": "2.1.0",
|
||||
"esbuild": "0.14.3",
|
||||
"fs-extra": "^10.0.1",
|
||||
"graphql": "^16.3.0",
|
||||
"graphql-scalars": "1.15.0",
|
||||
"graphql-scalars": "1.17.0",
|
||||
"js-yaml": "^4.1.0",
|
||||
"koa": "^2.13.4",
|
||||
"koa-body": "^4.2.0",
|
||||
@@ -34,40 +34,39 @@
|
||||
"koa-router": "^10.1.1",
|
||||
"koa-static-cache": "^5.1.4",
|
||||
"lodash": "^4.17.21",
|
||||
"lru-cache": "7.4.4",
|
||||
"mime-types": "^2.1.34",
|
||||
"lru-cache": "7.7.3",
|
||||
"mime-types": "^2.1.35",
|
||||
"minio": "7.0.25",
|
||||
"moment-timezone": "^0.5.34",
|
||||
"mongodb": "^3.7.3",
|
||||
"nanoid": "^3.3.1",
|
||||
"nodemailer": "^6.7.2",
|
||||
"nanoid": "^3.3.2",
|
||||
"nodemailer": "^6.7.3",
|
||||
"notp": "^2.0.3",
|
||||
"p-queue": "^7.2.0",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"require-resolve-hook": "^1.1.0",
|
||||
"semver": "^7.3.5",
|
||||
"serialize-javascript": "^6.0.0",
|
||||
"sockjs": "^0.3.24",
|
||||
"source-map-support": "^0.5.21",
|
||||
"superagent": "^7.1.1",
|
||||
"superagent": "^7.1.2",
|
||||
"thirty-two": "^1.0.2",
|
||||
"tx2": "^1.0.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/adm-zip": "^0.4.34",
|
||||
"@types/adm-zip": "^0.5.0",
|
||||
"@types/fs-extra": "^9.0.13",
|
||||
"@types/js-yaml": "^4.0.5",
|
||||
"@types/koa": "^2.13.4",
|
||||
"@types/koa-compress": "^4.0.3",
|
||||
"@types/koa-router": "^7.4.4",
|
||||
"@types/koa-static-cache": "^5.1.1",
|
||||
"@types/lodash": "^4.14.179",
|
||||
"@types/lru-cache": "^7.4.0",
|
||||
"@types/lodash": "^4.14.181",
|
||||
"@types/lru-cache": "^7.6.1",
|
||||
"@types/mime-types": "^2.1.1",
|
||||
"@types/minio": "^7.0.12",
|
||||
"@types/mongodb": "^3.6.20",
|
||||
"@types/nodemailer": "^6.4.4",
|
||||
"@types/notp": "^2.0.1",
|
||||
"@types/notp": "^2.0.2",
|
||||
"@types/semver": "^7.3.9",
|
||||
"@types/serialize-javascript": "^5.0.2",
|
||||
"@types/sockjs": "^0.3.33",
|
||||
|
||||
@@ -39,7 +39,7 @@ export function registerResolver(
|
||||
registerValue(typeName, key, value, description);
|
||||
const wrappedFunc = async (arg, ctx, info) => {
|
||||
const res = await func(arg, ctx, info);
|
||||
if (typeof res !== 'object') return res;
|
||||
if (typeof res !== 'object' || res === null) return res;
|
||||
const node = value.includes('!') ? value.split('!')[0] : value;
|
||||
if (handlers[node]) Object.assign(res, handlers[node]);
|
||||
ctx.parent = res;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/* eslint-disable simple-import-sort/imports */
|
||||
/* eslint-disable no-await-in-loop */
|
||||
/* eslint-disable no-eval */
|
||||
import 'reflect-metadata';
|
||||
import './init';
|
||||
import './interface';
|
||||
import path from 'path';
|
||||
|
||||
@@ -12,6 +12,7 @@ const coll = db.collection('task');
|
||||
const collEvent = db.collection('event');
|
||||
|
||||
async function getFirst(query: FilterQuery<Task>) {
|
||||
if (process.env.CI) return null;
|
||||
const q = { ...query };
|
||||
q.executeAfter = q.executeAfter || { $lt: new Date() };
|
||||
const res = await coll.findOneAndDelete(q, { sort: { priority: -1 } });
|
||||
|
||||
@@ -34,8 +34,13 @@ class MongoService implements BaseService {
|
||||
}
|
||||
|
||||
async start(opts: MongoConfig) {
|
||||
let mongourl = MongoService.buildUrl(opts);
|
||||
if (process.env.CI) {
|
||||
const { MongoMemoryServer } = require('mongodb-memory-server');
|
||||
const mongod = await MongoMemoryServer.create();
|
||||
mongourl = mongod.getUri();
|
||||
}
|
||||
this.opts = opts;
|
||||
const mongourl = MongoService.buildUrl(opts);
|
||||
this.client = await MongoClient.connect(mongourl, { useNewUrlParser: true, useUnifiedTopology: true });
|
||||
this.db = this.client.db(opts.name);
|
||||
await bus.parallel('database/connect', this.db);
|
||||
|
||||
@@ -13,6 +13,6 @@
|
||||
"hydrooj": "*"
|
||||
},
|
||||
"dependencies": {
|
||||
"superagent": "^7.1.1"
|
||||
"superagent": "^7.1.2"
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,6 @@
|
||||
"hydrooj": "*"
|
||||
},
|
||||
"dependencies": {
|
||||
"superagent": "^7.1.1"
|
||||
"superagent": "^7.1.2"
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,6 @@
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"preferUnplugged": true,
|
||||
"dependencies": {
|
||||
"superagent": "^7.1.1"
|
||||
"superagent": "^7.1.2"
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,6 @@
|
||||
"author": "undefined <i@undefined.moe>",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"sonic-channel": "^1.2.6"
|
||||
"sonic-channel": "^1.2.7"
|
||||
}
|
||||
}
|
||||
@@ -10,20 +10,20 @@
|
||||
"lint": "eslint ."
|
||||
},
|
||||
"devDependencies": {
|
||||
"@blueprintjs/core": "^3.53.0",
|
||||
"@fontsource/dm-mono": "^4.5.4",
|
||||
"@fontsource/fira-code": "^4.5.5",
|
||||
"@fontsource/inconsolata": "^4.5.2",
|
||||
"@fontsource/jetbrains-mono": "^4.5.3",
|
||||
"@fontsource/pt-mono": "^4.5.3",
|
||||
"@fontsource/roboto-mono": "^4.5.3",
|
||||
"@fontsource/source-code-pro": "^4.5.4",
|
||||
"@fontsource/ubuntu-mono": "^4.5.4",
|
||||
"@blueprintjs/core": "^3.54.0",
|
||||
"@fontsource/dm-mono": "^4.5.7",
|
||||
"@fontsource/fira-code": "^4.5.8",
|
||||
"@fontsource/inconsolata": "^4.5.4",
|
||||
"@fontsource/jetbrains-mono": "^4.5.5",
|
||||
"@fontsource/pt-mono": "^4.5.5",
|
||||
"@fontsource/roboto-mono": "^4.5.5",
|
||||
"@fontsource/source-code-pro": "^4.5.6",
|
||||
"@fontsource/ubuntu-mono": "^4.5.6",
|
||||
"@hydrooj/utils": "workspace:*",
|
||||
"@types/gulp-if": "^0.0.34",
|
||||
"@types/jquery": "^3.5.14",
|
||||
"@types/json-schema": "^7.0.9",
|
||||
"@types/katex": "^0.11.1",
|
||||
"@types/json-schema": "^7.0.11",
|
||||
"@types/katex": "^0.14.0",
|
||||
"@types/qrcode": "^1.4.2",
|
||||
"@types/redux-logger": "^3.0.9",
|
||||
"@types/sockjs-client": "^1.5.1",
|
||||
@@ -39,15 +39,15 @@
|
||||
"copy-webpack-plugin": "^6.4.1",
|
||||
"css-loader": "^4.3.0",
|
||||
"diff-dom": "^4.2.3",
|
||||
"echarts": "^5.3.1",
|
||||
"echarts": "^5.3.2",
|
||||
"emojis-keywords": "2.0.0",
|
||||
"emojis-list": "2.1.0",
|
||||
"esbuild-loader": "^2.18.0",
|
||||
"eslint": "^8.11.0",
|
||||
"eslint": "^8.12.0",
|
||||
"fancy-log": "^2.0.0",
|
||||
"file-loader": "^6.2.0",
|
||||
"friendly-errors-webpack-plugin": "^1.7.0",
|
||||
"graphiql": "^1.7.1",
|
||||
"graphiql": "^1.8.3",
|
||||
"gulp": "^4.0.2",
|
||||
"gulp-cli": "^2.3.0",
|
||||
"gulp-iconfont": "^11.0.1",
|
||||
@@ -64,7 +64,7 @@
|
||||
"monaco-editor-nls": "^2.0.0",
|
||||
"monaco-editor-webpack-plugin": "^7.0.1",
|
||||
"monaco-themes": "^0.4.0",
|
||||
"nanoid": "^3.3.1",
|
||||
"nanoid": "^3.3.2",
|
||||
"normalize.css": "^8.0.1",
|
||||
"nprogress": "^0.2.0",
|
||||
"pickadate": "^3.6.4",
|
||||
@@ -78,7 +78,7 @@
|
||||
"raw-loader": "^4.0.2",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-redux": "^7.2.6",
|
||||
"react-redux": "^7.2.8",
|
||||
"react-split-pane": "^0.1.92",
|
||||
"reconnecting-websocket": "^4.4.0",
|
||||
"redux": "^4.1.2",
|
||||
@@ -91,7 +91,7 @@
|
||||
"speed-measure-webpack-plugin": "^1.5.0",
|
||||
"sticky-kit": "^1.1.3",
|
||||
"style-loader": "^2.0.0",
|
||||
"stylus": "^0.56.0",
|
||||
"stylus": "^0.57.0",
|
||||
"stylus-loader": "^3.0.2",
|
||||
"tether": "^1.4.7",
|
||||
"tether-drop": "^1.4.2",
|
||||
@@ -99,7 +99,7 @@
|
||||
"through2": "^4.0.2",
|
||||
"timeago-react": "^3.0.4",
|
||||
"timeago.js": "^4.0.2",
|
||||
"vditor": "^3.8.12",
|
||||
"vditor": "^3.8.13",
|
||||
"vinyl-buffer": "^1.0.1",
|
||||
"web-streams-polyfill": "^3.2.0",
|
||||
"webpack": "^4.46.0",
|
||||
@@ -112,7 +112,7 @@
|
||||
"fs-extra": "^10.0.1",
|
||||
"js-yaml": "^4.1.0",
|
||||
"jsesc": "^3.0.2",
|
||||
"katex": "^0.15.2",
|
||||
"katex": "^0.15.3",
|
||||
"lodash": "^4.17.21",
|
||||
"markdown-it": "^12.3.2",
|
||||
"markdown-it-anchor": "^8.4.1",
|
||||
@@ -124,7 +124,7 @@
|
||||
"mongodb": "^3.7.3",
|
||||
"nunjucks": "^3.2.3",
|
||||
"p-queue": "^7.2.0",
|
||||
"react-query": "^3.34.16",
|
||||
"react-query": "^3.34.19",
|
||||
"streamsaver": "^2.0.6",
|
||||
"xss": "^1.0.11"
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"js-yaml": "^4.1.0",
|
||||
"moment": "^2.29.1",
|
||||
"mongodb": "^3.7.3",
|
||||
"systeminformation": "^5.11.8"
|
||||
"systeminformation": "^5.11.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/fs-extra": "^9.0.13",
|
||||
|
||||
@@ -12,16 +12,16 @@
|
||||
"chrome-finder": "^1.0.7",
|
||||
"jsdom": "^19.0.0",
|
||||
"lodash": "^4.17.21",
|
||||
"puppeteer-core": "^13.5.1",
|
||||
"puppeteer-core": "^13.5.2",
|
||||
"puppeteer-extra": "^3.2.3",
|
||||
"puppeteer-extra-plugin-portal": "^3.0.1",
|
||||
"puppeteer-extra-plugin-stealth": "^2.9.0",
|
||||
"superagent": "^7.1.1",
|
||||
"superagent": "^7.1.2",
|
||||
"superagent-proxy": "^3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jsdom": "^16.2.14",
|
||||
"@types/lodash": "^4.14.179",
|
||||
"@types/lodash": "^4.14.181",
|
||||
"@types/superagent": "^4.1.15",
|
||||
"@types/superagent-proxy": "^3.0.0"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
process.env.CI = true;
|
||||
require('hydrooj/bin/hydrooj');
|
||||
require('./main');
|
||||
@@ -0,0 +1,78 @@
|
||||
import assert from 'assert';
|
||||
import autocannon from 'autocannon';
|
||||
import { writeFileSync } from 'fs-extra';
|
||||
import * as supertest from 'supertest';
|
||||
import * as bus from 'hydrooj/src/service/bus';
|
||||
|
||||
const Root = {
|
||||
username: 'root',
|
||||
password: '123456',
|
||||
creditionals: null,
|
||||
};
|
||||
|
||||
describe('App', () => {
|
||||
let agent: supertest.SuperAgentTest;
|
||||
before('init', function init(done) {
|
||||
this.timeout(30000);
|
||||
bus.on('app/started', () => setTimeout(() => {
|
||||
agent = supertest.agent(require('hydrooj/src/service/server').server);
|
||||
done();
|
||||
}, 2000));
|
||||
});
|
||||
|
||||
const routes = ['/', '/api', '/p', '/contest', '/homework', '/user/1', '/training'];
|
||||
routes.forEach((route) => it(`GET ${route}`, () => agent.get(route).expect(200)));
|
||||
|
||||
it('API user', async () => {
|
||||
await agent.get('/api?{user(id:1){uname}}').expect({ data: { user: { uname: 'Hydro' } } });
|
||||
await agent.get('/api?{user(id:2){uname}}').expect({ data: { user: null } });
|
||||
});
|
||||
|
||||
it('Create User', async () => {
|
||||
const redirect = await agent.post('/register')
|
||||
.send({ mail: 'test@example.com' })
|
||||
.expect(302)
|
||||
.then((res) => res.headers.location);
|
||||
await agent.post(redirect)
|
||||
.send({ uname: Root.username, password: Root.password, verifyPassword: Root.password })
|
||||
.expect(302);
|
||||
});
|
||||
|
||||
it('Login', async () => {
|
||||
const cookie = await agent.post('/login')
|
||||
.send({ uname: Root.username, password: Root.password })
|
||||
.expect(302)
|
||||
.then((res) => res.headers['set-cookie']);
|
||||
Root.creditionals = cookie;
|
||||
});
|
||||
|
||||
it('API registered user', async () => {
|
||||
await agent.get('/api?{user(id:2){uname}}').expect({ data: { user: { uname: 'root' } } });
|
||||
});
|
||||
|
||||
// TODO add more tests
|
||||
|
||||
const results: Record<string, autocannon.Result> = {};
|
||||
if (process.env.BENCHMARK) {
|
||||
routes.forEach((route) => it(`Performance test ${route}`, async function test() {
|
||||
this.timeout(60000);
|
||||
await global.Hydro.model.system.set('limit.global', 99999);
|
||||
const result = await autocannon({ url: `http://localhost:8888${route}` });
|
||||
assert(result.errors === 0, `test ${route} returns errors`);
|
||||
results[route] = result;
|
||||
}));
|
||||
}
|
||||
|
||||
after(() => {
|
||||
const metrics = [];
|
||||
for (const key in results) {
|
||||
metrics.push({
|
||||
name: `Benchmark - ${key} - Req/sec`,
|
||||
unit: 'Req/sec',
|
||||
value: results[key].requests.average,
|
||||
});
|
||||
}
|
||||
writeFileSync('./benchmark.json', JSON.stringify(metrics, null, 2));
|
||||
setTimeout(() => process.exit(0), 1000);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user