Skip to content
This repository was archived by the owner on Mar 22, 2020. It is now read-only.

Commit fdbbef9

Browse files
committed
init
0 parents  commit fdbbef9

11 files changed

Lines changed: 2028 additions & 0 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
repo/
2+
node_modules
3+
.idea/

app.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
const Koa = require('koa');
2+
const bodyParser = require('koa-bodyparser');
3+
const logger = require('koa-logger');
4+
const app = new Koa();
5+
const debug = require('debug')('app');
6+
const Router = require('koa-router');
7+
8+
const router = new Router();
9+
10+
router.post('/hook', require('./handlers/hook').post);
11+
12+
app.use(logger());
13+
14+
app.use(bodyParser());
15+
16+
app.use(router.routes());
17+
app.use(router.allowedMethods());
18+
19+
module.exports = app;

bin/server.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
let app = require('../app');
2+
const debug = require('debug')('server');
3+
4+
app.listen(3000);

config.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
const path = require('path');
2+
3+
const config = {
4+
projectRoot: process.cwd(),
5+
repoRoot: path.join(process.cwd(), 'repo'),
6+
secret: require('/js/secret.javascript-tutorial-translate-hook')
7+
};
8+
9+
module.exports = config;

ecosystem.json

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"apps": [
3+
{
4+
"name": "javascript",
5+
"script": "bin/server.js",
6+
"instances": "1",
7+
"node_args": "",
8+
"exec_mode": "cluster_mode",
9+
"max_memory_restart": "2G",
10+
"kill_timeout": 5000,
11+
"wait_ready": true,
12+
"log_file": "/var/log/node/javascript.log",
13+
"error_file": "/var/log/node/javascript-err.log",
14+
"out_file": "/var/log/node/javascript-out.log",
15+
"cwd": "/js/javascript-tutorial-translate-hook",
16+
"env": {
17+
"HOST": "127.0.0.1",
18+
"PORT": "3000",
19+
"PM2_GRACEFUL_LISTEN_TIMEOUT": 5000,
20+
"PM2_GRACEFUL_TIMEOUT": 5000,
21+
"ASSET_VERSIONING": "file",
22+
"NODE_ENV": "production"
23+
}
24+
}
25+
]
26+
}

handlers/hook.js

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
const crypto = require('crypto');
2+
const config = require('../config');
3+
const debug = require('debug')('hook');
4+
const onUpdateHook = require('../lib/onUpdateHook');
5+
6+
exports.post = async function(ctx) {
7+
8+
let signature = ctx.get('x-hub-signature');
9+
let event = ctx.get('x-github-event');
10+
let id = ctx.get('x-github-delivery');
11+
12+
if (!signature) {
13+
ctx.throw(400, 'No X-Hub-Signature found on request');
14+
}
15+
16+
if (!event) {
17+
ctx.throw(400, 'No X-Github-Event found on request');
18+
}
19+
20+
if (!id) {
21+
ctx.throw(400, 'No X-Github-Delivery found on request');
22+
}
23+
24+
//debug("github hook", ctx.request);
25+
26+
debug("Hook data", ctx.request.body);
27+
28+
let repo = config.secret.repos[ctx.request.body.repository.full_name];
29+
if (!repo.lang) {
30+
// __proto__ as repo name
31+
this.throw(400);
32+
}
33+
34+
// koa-bodyparser gives that
35+
debug(ctx.request.rawBody);
36+
37+
signature = signature.replace(/^sha1=/, '');
38+
let computedSignature = crypto
39+
.createHmac('sha1', Buffer.from(repo.githubSecret, 'utf-8'))
40+
.update(ctx.request.rawBody)
41+
.digest('hex');
42+
43+
debug("Compare signature", computedSignature, signature);
44+
45+
if (computedSignature !== signature) {
46+
ctx.throw(400, 'X-Hub-Signature does not match blob signature');
47+
}
48+
49+
if (ctx.request.body.ref !== 'refs/heads/master') {
50+
// ignore non-master pushes
51+
ctx.body = {ok: true};
52+
return;
53+
}
54+
55+
56+
ctx.body = {ok: true};
57+
58+
// don't wait for it! (async)
59+
onUpdateHook(ctx.request.body);
60+
61+
};

lib/countTranslation.js

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
'use strict';
2+
3+
const glob = require('glob');
4+
const config = require('config');
5+
const path = require('path');
6+
const fs = require('fs');
7+
const jsdiff = require('diff');
8+
const log = require('log')();
9+
10+
module.exports = function () {
11+
12+
return function () {
13+
let args = require('yargs')
14+
.demand(['lang'])
15+
.argv;
16+
17+
return async function () {
18+
19+
let root = path.dirname(config.tutorialRoot);
20+
let rootEn = path.join(root, 'javascript-tutorial-en');
21+
let rootLang = path.join(root, 'javascript-tutorial-' + args.lang);
22+
23+
log.debug(`Compare ${rootEn} vs ${rootLang}`);
24+
let filesFrom = glob.sync('**/*.md', {cwd: rootEn}).filter(f => parseInt(f));
25+
26+
let filesTranslated = 0;
27+
let filesMissing = 0;
28+
let filesSimilar = 0;
29+
30+
for (let relPath of filesFrom) {
31+
let fileFrom = path.join(rootEn, relPath);
32+
let fileLang = path.join(rootLang, relPath);
33+
34+
log.debug(relPath);
35+
if (!fs.existsSync(fileLang)) {
36+
filesMissing++;
37+
log.debug("MISSING");
38+
continue;
39+
}
40+
41+
if (fs.statSync(fileFrom).size === 0) {
42+
// ignore zero files, don't count as translated
43+
// this way new repo translation starts with zero
44+
continue;
45+
}
46+
47+
let fileFromContent = fs.readFileSync(fileFrom, {encoding: 'utf8'});
48+
let fileLangContent = fs.readFileSync(fileLang, {encoding: 'utf8'});
49+
50+
fileFromContent = stripYamlHeader(fileFromContent);
51+
fileLangContent = stripYamlHeader(fileLangContent);
52+
53+
fileFromContent = stripCode(fileFromContent);
54+
fileLangContent = stripCode(fileLangContent);
55+
56+
fileFromContent = fileFromContent.trim();
57+
fileLangContent = fileLangContent.trim();
58+
// log.debug(fileFromContent);
59+
60+
let linesTotal = (fileFromContent.match(/\n+/g) || []).length;
61+
62+
/*
63+
64+
let added = 0;
65+
let removed = 0;
66+
try {
67+
let cmd = `git diff --no-index --numstat --patience ${esc(fileFrom)} ${esc(fileLang)}`;
68+
log.debug(cmd);
69+
let compare = execSync(cmd, {encoding: 'utf8'});
70+
} catch(err) {
71+
if (err.status !== 1) {
72+
throw err;
73+
}
74+
[added, removed] = err.output[1].trim().split('\t');
75+
}
76+
*/
77+
let diff = jsdiff.diffLines(fileFromContent, fileLangContent);
78+
79+
80+
let added = 0;
81+
let removed = 0;
82+
for(let obj of diff) {
83+
if (obj.added) added += obj.count;
84+
if (obj.removed) removed += obj.count;
85+
}
86+
87+
if (added + removed > linesTotal / 3) {
88+
log.debug("TRANSLATED", added, removed, linesTotal);
89+
filesTranslated++;
90+
} else {
91+
log.debug("SIMILAR", added, removed, linesTotal);
92+
filesSimilar++;
93+
}
94+
95+
// log.debug("RESULT", added, removed, linesTotal);
96+
//return;
97+
// if (added == 0 && removed == 0)
98+
//log.debug("RESULT", added, removed, linesTotal);
99+
100+
}
101+
102+
log.info("TOTAL", { filesTranslated, filesMissing, filesSimilar });
103+
}();
104+
105+
};
106+
};
107+
108+
109+
function stripCode(content) {
110+
return content.replace(/(^|\n[ \t]*)```(js|css|html)[\s\S]+\n[ \t]*```/gim, '\n');
111+
}
112+
113+
function stripYamlHeader(content) {
114+
let parts = content.split('\n---\n');
115+
if (parts.length === 1) {
116+
return content;
117+
}
118+
119+
return parts.slice(1).join('\n---\n');
120+
}
121+

lib/onUpdateHook.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
2+
const config = require("../config");
3+
const path = require("path");
4+
const git = require("nodegit");
5+
const exec = require('mz/child_process');
6+
const debug = require('debug')('onUpdateRepo');
7+
const fs = require('fs');
8+
9+
module.exports = async function(githubHookInfo) {
10+
let repoDir = path.join(config.repoRoot, githubHookInfo.repository.name);
11+
12+
if (!fs.existsSync(repoDir)) {
13+
debug("Clone " + githubHookInfo.repository.clone_url + " to " + repoDir);
14+
await git.Clone(githubHookInfo.repository.clone_url, repoDir);
15+
}
16+
17+
let repo = await git.Repository.open(repoDir);
18+
19+
await repo.fetch('origin');
20+
let head = await repo.getReferenceCommit("refs/remotes/origin/master");
21+
22+
debug("hard reset to " + head);
23+
24+
// 3 = hard reset
25+
await git.Reset.reset(repo, head, 3, {});
26+
};
27+
28+

nodemon.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"verbose": true,
3+
"ignore": ["**/repo/**"]
4+
}

0 commit comments

Comments
 (0)