Skip to content

Instantly share code, notes, and snippets.

@matejc
Last active June 4, 2016 17:36
Show Gist options
  • Save matejc/7b2fffb4f71760e5fac7fffbb6d048fd to your computer and use it in GitHub Desktop.
Save matejc/7b2fffb4f71760e5fac7fffbb6d048fd to your computer and use it in GitHub Desktop.
set -e
NAME="$1"
COMMIT="$2"
BRANCH="$3"
REGISTRY="$4"
REPO="$PWD"
SRC="$REPO-$COMMIT-src"
echo $NAME $COMMIT $REPO $SRC
err_handler() {
echo "$NAME: Error on line $1 in file $0"
}
trap 'err_handler $LINENO' ERR
test -n "$NAME"
test -n "$COMMIT"
test -n "$REPO"
test -n "$BRANCH"
rm -rf "$SRC"
git clone $REPO "$SRC"
cd "$SRC"
TAGS="--tag=$NAME:$BRANCH"
test -z "$REGISTRY" || {
TAGS="$TAGS --tag=$REGISTRY/$NAME:$BRANCH --tag=$REGISTRY/$NAME:$COMMIT";
}
docker build $TAGS "$SRC"
test -z "$REGISTRY" || {
docker push $REGISTRY/$NAME:$BRANCH;
docker push $REGISTRY/$NAME:$COMMIT;
}
echo "Deployed $NAME at `date`, tags: $REGISTRY/$NAME:$BRANCH, $REGISTRY/$NAME:$COMMIT"
var Tail = require('always-tail');
var auth = require('basic-auth');
var bcrypt = require('bcrypt');
var pushover = require('pushover');
var spawn = require('child_process').spawn;
var fs = require('fs');
var url = require('url');
var path = require('path');
var options = require('./options.json');
var repos = pushover(options.repos);
var runtime = { connectionCount: 0 };
options.port = options.port || 30003;
rmDir = function(dirPath) {
var files = [];
try {
files = fs.readdirSync(dirPath);
} catch (e) {
return;
}
if (files.length > 0)
for (var i = 0; i < files.length; i++) {
var filePath = dirPath + '/' + files[i];
if (fs.statSync(filePath).isFile())
fs.unlinkSync(filePath);
else
rmDir(filePath);
}
fs.rmdirSync(dirPath);
};
repos.on('push', function (push) {
var name = [push.repo, push.branch].join('_');
var repositories = require('./repositories.json');
var script = path.join(__dirname, 'build.sh');
var exists = fs.existsSync(script);
if (!exists || !repositories[push.repo] || repositories[push.repo].branch !== push.branch) {
return push.reject();
}
var cwd = fs.existsSync(push.cwd) && push.cwd;
cwd = cwd || fs.existsSync(push.cwd+'.git') && (push.cwd+'.git');
console.log('push ' + push.repo + '/' + push.commit + ' (' + push.branch + ') cwd:' + cwd);
push.on('success', function() {console.log('success');});
push.on('exit', function(code) {
console.log('push code:', code);
if (code !== 0) {
return;
}
var proc = spawn(script, [push.repo, push.commit, push.branch, repositories[push.repo].registry || ''], {cwd: cwd});
proc.stdout.setEncoding('utf8');
proc.stderr.setEncoding('utf8');
proc.stdout.pipe(process.stdout);
proc.stderr.pipe(process.stderr);
// proc.stdout.on('data', function(buf) { console.log(buf?buf.toString():''); });
// proc.stderr.on('data', function(buf) { console.error(buf?buf.toString():''); });
proc.on('exit', function (code, signal) {
console.log(script+': '+code);
if (cwd.startsWith(options.repos)) {
rmDir(cwd);
}
});
});
push.accept();
});
repos.on('fetch', function (fetch) {
console.log('fetch ' + fetch.repo + '/' + fetch.commit);
fetch.accept();
});
bcrypt.genSalt(3, function(err, salt) {
bcrypt.hash(options.password, salt, function(err, hash) {
options.hash = hash;
});
});
var http = require('http');
var server = http.createServer(function (req, res) {
var credentials = auth(req);
new Promise(function(resolve, reject) {
if (!credentials || credentials.name !== options.username || !credentials.pass) {
return reject("Missing credentials");
}
bcrypt.compare(credentials.pass, options.hash, function(err, ok) {
if(!err && ok){
resolve();
}else{
reject(err);
}
});
})
.then(function() {
var urlData = url.parse(req.url, true) || {};
if (urlData.query && urlData.query.log) {
var fs = require('fs');
var filename = '/var/log/'+urlData.query.log;
if (!fs.existsSync(filename) || filename.indexOf('..') !== -1) {
res.statusCode = 400;
res.end('bad request');
}
var size = fs.statSync(filename).size;
var options = { interval: 1000 };
if (typeof size === 'number') {
options.start = size > 4096 ? size - 4096 : 0;
}
var tail = new Tail(filename, '\n', options);
tail.on('line', function(data) {
res.write(data+'\n');
});
tail.on('error', function(data) {
console.error('tail error:', data);
res.end();
tail.unwatch();
});
console.time('tail: '+filename);
runtime.connectionCount++;
res.setHeader('Transfer-Encoding', 'chunked');
res.setHeader('Content-Type', 'text/plain');
res.on('close', function() {
console.timeEnd('tail: '+filename);
runtime.connectionCount--;
if (runtime.connectionCount < 1) {
setTimeout(function() {
tail.unwatch();
res.end();
}, 1000);
}
});
tail.watch();
} else {
repos.handle(req, res);
}
})
.catch(function(err) {
res.statusCode = 401;
res.setHeader('WWW-Authenticate', 'Basic realm="Enter credentials"');
res.end('Access denied');
});
});
server.listen(options.port);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment