├── lib ├── index.js ├── routers │ ├── gitlab.js │ └── github.js ├── server.js └── queue.js ├── .gitignore ├── scripts ├── init_repo.sh ├── mirror_tag.sh ├── mirror_branch.sh ├── mirror_pr.sh ├── mirror.sh └── report_ci.sh └── package.json /lib/index.js: -------------------------------------------------------------------------------- 1 | require("./server").start() 2 | 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | git_workdir 3 | pm2.json 4 | parity_git -------------------------------------------------------------------------------- /scripts/init_repo.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "clear $DIR" 4 | rm -rf $DIR 5 | 6 | echo "Clonining $SRC_ADDRESS into $DIR" 7 | git clone $GIT_SRC_ADDRESS $DIR 8 | -------------------------------------------------------------------------------- /scripts/mirror_tag.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd $DIR 4 | git checkout master 5 | git pull 6 | 7 | git fetch origin tag $TAG_NAME -f 8 | git checkout $TAG_NAME 9 | git push $GIT_TRG_ADDRESS $TAG_NAME -f 10 | -------------------------------------------------------------------------------- /scripts/mirror_branch.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd $DIR 4 | git checkout master 5 | git pull 6 | 7 | git fetch origin $REF:$BRANCH_NAME -f 8 | git checkout $BRANCH_NAME 9 | git push $GIT_TRG_ADDRESS $BRANCH_NAME -f 10 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "async": "^2.1.4", 4 | "body-parser": "^1.15.2", 5 | "express": "^4.14.0", 6 | "git-js": "^1.1.1", 7 | "lodash": "^4.17.4", 8 | "mkdirp": "^0.5.1", 9 | "rx": "^4.1.0", 10 | "simple-git": "^1.65.0" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /scripts/mirror_pr.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd $DIR 4 | git checkout master 5 | git pull 6 | 7 | echo "get the PR" 8 | PR_BRANCH=pr-$PR_ID 9 | 10 | git fetch origin pull/$PR_ID/head:$PR_BRANCH -f 11 | git checkout $PR_BRANCH 12 | 13 | echo "push to gitlab" 14 | git push $GIT_TRG_ADDRESS $PR_BRANCH -f 15 | -------------------------------------------------------------------------------- /scripts/mirror.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | if [ -d "$DIR" ]; then 5 | cd $DIR 6 | echo "Updating the local clone" 7 | git remote update 8 | else 9 | echo Cloning $GIT_SRC_ADDRESS to $DIR 10 | git clone --mirror $GIT_SRC_ADDRESS $DIR 11 | 12 | cd $DIR 13 | fi 14 | 15 | echo Pusing to $GIT_TRG_ADDRESS 16 | 17 | git push --mirror $GIT_TRG_ADDRESS 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /lib/routers/gitlab.js: -------------------------------------------------------------------------------- 1 | var { q, makeReportCi } = require("../queue"); 2 | 3 | module.exports = require("express").Router().post("/", function (req, res) { 4 | var event = req.get("X-Gitlab-Event") 5 | if (event == "Pipeline Hook") { 6 | console.log("Gitlab pipeline event") 7 | var id = req.body.object_attributes.id; 8 | var sha = req.body.object_attributes.sha; 9 | var status = req.body.object_attributes.status; 10 | q.push(makeReportCi(id, sha, status)) 11 | } 12 | res.status(200).end(); 13 | }) 14 | -------------------------------------------------------------------------------- /scripts/report_ci.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ci_web_url="https://${GITLAB_HOSTNAME}/${GITLAB_REPOSITORY}/pipelines/${PIPELINE_ID}" 4 | 5 | if [ "$ci_status" = "success" ] 6 | then 7 | curl -d '{"state":"success", "target_url": "'${ci_web_url}'", "context": "gitlab-ci"}' -H "Authorization: token ${GITHUB_TOKEN}" -H "Accept: application/vnd.github.antiope-preview+json" -X POST --silent "https://api.github.com/repos/${GITHUB_REPOSITORY}/statuses/${GITHUB_SHA}" 8 | exit 0 9 | elif [ "$ci_status" = "failed" ] 10 | then 11 | curl -d '{"state":"failure", "target_url": "'${ci_web_url}'", "context": "gitlab-ci"}' -H "Authorization: token ${GITHUB_TOKEN}" -H "Accept: application/vnd.github.antiope-preview+json" -X POST --silent "https://api.github.com/repos/${GITHUB_REPOSITORY}/statuses/${GITHUB_SHA}" 12 | exit 1 13 | elif [ "$ci_status" = "running" ] 14 | then 15 | curl -d '{"state":"pending", "target_url": "'${ci_web_url}'", "context": "gitlab-ci"}' -H "Authorization: token ${GITHUB_TOKEN}" -H "Accept: application/vnd.github.antiope-preview+json" -X POST --silent "https://api.github.com/repos/${GITHUB_REPOSITORY}/statuses/${GITHUB_SHA}" > /dev/null 16 | exit 0 17 | fi -------------------------------------------------------------------------------- /lib/server.js: -------------------------------------------------------------------------------- 1 | var express = require("express"), 2 | app = express(), 3 | fs = require("fs"), 4 | http = require("http"), 5 | https = require("https") 6 | 7 | 8 | app.use(function (req, res, next) { 9 | res.header("Access-Control-Allow-Origin", "*"); 10 | res.header("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE, PATCH"); 11 | res.header("Access-Control-Allow-Headers", "Accept, Content-Type, Authorization, " 12 | + "X-Requested-With"); 13 | 14 | next(); 15 | }); 16 | 17 | 18 | 19 | app.use(require("body-parser").json({ limit: '50mb' })); 20 | 21 | app.get('/', function (req, res) { 22 | res.json({ 23 | name: "Gitsync", 24 | status: "OK" 25 | }); 26 | }); 27 | 28 | 29 | app.use("/github", require("./routers/github")) 30 | 31 | app.use("/gitlab", require("./routers/gitlab")) 32 | 33 | var port = process.env.PORT || 80, 34 | sslPort = process.env.SSL_PORT || 443, 35 | httpServer, 36 | httpsServer 37 | 38 | 39 | module.exports = { 40 | start: function () { 41 | http.createServer(app).listen(port, (err, server) => { 42 | console.log("http server listening on", port) 43 | 44 | httpServer = server 45 | }) 46 | 47 | if (process.env.SSL_KEY && process.env.SSL_CERT) { 48 | https.createServer({ 49 | key: fs.readFileSync(process.env.SSL_KEY), 50 | cert: fs.readFileSync(process.env.SSL_CERT) 51 | }, app).listen(sslPort, (err, server) => { 52 | console.log("https server listening on", sslPort) 53 | httpsServer = server 54 | }); 55 | } 56 | }, 57 | stop: function () { 58 | httpServer.close() 59 | httpsServer.close() 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /lib/routers/github.js: -------------------------------------------------------------------------------- 1 | var fs = require("fs"), 2 | _ = require("lodash"), 3 | crypto = require("crypto"), 4 | { q, makeInit, makeMirrorPr, makeMirrorTag, makeMirrorBranch } = require("../queue"); 5 | 6 | q.push(makeInit()) 7 | 8 | var getRefName = (ref) => ref.substring(_.indexOf(ref, "/", _.indexOf(ref, "/") + 1) + 1) 9 | 10 | module.exports = require("express").Router().post("/", function (req, res) { 11 | var sig = req.get("x-hub-signature"), 12 | hmac = crypto.createHmac(sig.split("=")[0], process.env.GITHUB_WEBHOOK_SECRET) 13 | 14 | hmac.update(JSON.stringify(req.body), "utf-8") 15 | 16 | if (hmac.digest("hex") !== sig.split("=")[1]) { 17 | res.status(403) 18 | res.send("Invalid signature") 19 | return 20 | } 21 | 22 | var event = req.get("X-GitHub-Event") 23 | 24 | if (event === "push") { 25 | console.log("Push event"); 26 | 27 | var ref = req.body.ref, 28 | refSplit = ref.split("/") 29 | 30 | console.log("ref:", ref); 31 | 32 | var refName = getRefName(ref) 33 | 34 | if (refSplit[1] === "tags") { 35 | console.log("Pushing a tag:", refName); 36 | 37 | q.push(makeMirrorTag(refName)) 38 | } else if (refSplit[1] === "heads") { 39 | console.log("Pushing a branch:", refName); 40 | 41 | q.push(makeMirrorBranch(ref, refName)) 42 | } 43 | 44 | } else if (event === "pull_request") { 45 | var head = req.body.pull_request.head 46 | 47 | console.log("Pull request event"); 48 | console.log("action", req.body.action) 49 | console.log("PR number", req.body.number); 50 | console.log("head ref", head.ref); 51 | console.log("head sha", head.sha); 52 | console.log("head fork?", head.repo.fork); 53 | console.log("head clone_url", head.repo.clone_url); 54 | 55 | if (_.includes(["opened", "reopened", "synchronize"], req.body.action) && head.repo.fork) { 56 | // Only mirror pr from forks 57 | console.log("SYNC!"); 58 | 59 | q.push(makeMirrorPr(req.body.number)) 60 | } 61 | } 62 | 63 | res.status(200).end() 64 | }) 65 | 66 | 67 | -------------------------------------------------------------------------------- /lib/queue.js: -------------------------------------------------------------------------------- 1 | var async = require("async"), 2 | { exec } = require("child_process"); 3 | 4 | var q = async.queue((task, cb) => { 5 | task(cb) 6 | }) 7 | 8 | q.drain = function () { 9 | console.log('No new jobs'); 10 | }; 11 | 12 | var scriptCb = (cb) => { 13 | return (err, stdout, stderr) => { 14 | console.log(`stdout: ${stdout}`); 15 | console.log(`stderr: ${stderr}`); 16 | 17 | cb(err) 18 | } 19 | } 20 | 21 | const ENV = process.env; 22 | const DIR = ENV.GIT_WORKING_DIR + "/" + ENV.REPO; 23 | const GITHUB_REPOSITORY = `${ENV.GITHUB_ORG}/${ENV.REPO}`; 24 | const GITLAB_REPOSITORY = `${ENV.GITLAB_ORG}/${ENV.REPO}`; 25 | const GIT_SRC_ADDRESS = `https://${ENV.GITHUB_USERNAME}:${ENV.GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}`; 26 | const GIT_TRG_ADDRESS = `https://${ENV.GITLAB_USERNAME}:${ENV.GITLAB_TOKEN}@${ENV.GITLAB_HOSTNAME}/${GITLAB_REPOSITORY}`; 27 | 28 | var makeInit = () => { 29 | return (cb) => { 30 | exec("scripts/init_repo.sh", { 31 | env: { 32 | DIR, 33 | GIT_SRC_ADDRESS 34 | } 35 | }, scriptCb(cb)) 36 | } 37 | }, makeMirrorPr = (prId) => { 38 | return (cb) => { 39 | exec("scripts/mirror_pr.sh", { 40 | env: { 41 | DIR, 42 | PR_ID: prId, 43 | GIT_TRG_ADDRESS, 44 | } 45 | }, scriptCb(cb)) 46 | } 47 | }, makeMirrorTag = (tagName) => { 48 | return (cb) => { 49 | exec("scripts/mirror_tag.sh", { 50 | env: { 51 | DIR, 52 | TAG_NAME: tagName, 53 | GIT_TRG_ADDRESS, 54 | } 55 | }, scriptCb(cb)) 56 | } 57 | }, makeMirrorBranch = (ref, branchName) => { 58 | return (cb) => { 59 | exec("scripts/mirror_branch.sh", { 60 | env: { 61 | DIR, 62 | REF: ref, 63 | BRANCH_NAME: branchName, 64 | GIT_TRG_ADDRESS, 65 | } 66 | }, scriptCb(cb)) 67 | } 68 | }, makeReportCi = (ci_id, sha, status) => { 69 | return (cb) => { 70 | exec("scripts/report_ci.sh", { 71 | env: { 72 | GITHUB_SHA: sha, 73 | GITHUB_REPOSITORY, 74 | GITHUB_TOKEN: process.env.GITHUB_TOKEN, 75 | PIPELINE_ID: ci_id, 76 | ci_status: status, 77 | GITLAB_HOSTNAME: ENV.GITLAB_HOSTNAME, 78 | GITLAB_REPOSITORY, 79 | } 80 | }, scriptCb(cb)) 81 | } 82 | } 83 | 84 | module.exports = { q, makeInit, makeMirrorPr, makeMirrorTag, makeMirrorBranch, makeReportCi }; --------------------------------------------------------------------------------