Commit 2d22adb2 authored by Johannes Zellner's avatar Johannes Zellner

Create scaffolding for gitlab type

parent dcd2dc1f
......@@ -21,6 +21,7 @@ module.exports = exports = {
projects: {
list: projectsList,
listByType: projectsListByType,
add: projectsAdd,
get: projectsGet,
update: projectsUpdate,
......@@ -79,6 +80,20 @@ function projectsList(userId, callback) {
});
}
function projectsListByType(userId, type, callback) {
assert.strictEqual(typeof userId, 'string');
assert.strictEqual(typeof type, 'string');
assert.strictEqual(typeof callback, 'function');
db.query('SELECT projects.*,releases.version,releases.createdAt FROM projects LEFT JOIN releases on releases.id = (SELECT releases.id FROM releases WHERE projectId=projects.id ORDER BY createdAt DESC LIMIT 1) WHERE userId=? AND type=?', [ userId, type ], function (error, result) {
if (error) return callback(error);
result.forEach(projectPostprocess);
callback(null, result);
});
}
function projectsAdd(project, callback) {
assert.strictEqual(typeof project, 'object');
assert.strictEqual(typeof callback, 'function');
......
'use strict';
var assert = require('assert'),
async = require('async'),
GitHub = require('github-api');
module.exports = exports = {
......
'use strict';
var assert = require('assert'),
superagent = require('superagent');
module.exports = exports = {
verifyToken: verifyToken,
getStarred: getStarred,
getReleases: getReleases,
getCommit: getCommit
};
function verifyToken(token, callback) {
assert.strictEqual(typeof token, 'string');
assert.strictEqual(typeof callback, 'function');
callback(new Error('not implemented'));
}
function getStarred(token, callback) {
assert.strictEqual(typeof token, 'string');
assert.strictEqual(typeof callback, 'function');
callback(new Error('not implemented'));
}
function getReleases(token, project, callback) {
assert.strictEqual(typeof token, 'string');
assert.strictEqual(typeof project, 'object');
assert.strictEqual(typeof callback, 'function');
// https://gitlab.example.com/api/v4/projects/24/releases
callback(new Error('not implemented'));
}
function getCommit(token, project, sha, callback) {
assert.strictEqual(typeof token, 'string');
assert.strictEqual(typeof project, 'object');
assert.strictEqual(typeof sha, 'string');
assert.strictEqual(typeof callback, 'function');
callback(new Error('not implemented'));
}
......@@ -9,6 +9,7 @@ var assert = require('assert'),
handlebars = require('handlebars'),
debug = require('debug')('releasebell/tasks'),
smtpTransport = require('nodemailer-smtp-transport'),
gitlab = require('./gitlab.js'),
github = require('./github.js');
module.exports = exports = {
......@@ -39,7 +40,7 @@ function run() {
debug('run: start');
syncStarred(function (error) {
syncProjects(function (error) {
if (error) console.error(error);
syncReleases(function (error) {
......@@ -49,7 +50,8 @@ function run() {
if (error) console.error(error);
// just keep polling for good every hour
setTimeout(run, 60 * 60 * 1000);
setTimeout(run, 5 * 1000);
// setTimeout(run, 60 * 60 * 1000);
tasksActive = false;
debug('run: done');
......@@ -58,39 +60,38 @@ function run() {
});
}
function syncStarred(callback) {
function syncProjects(callback) {
assert.strictEqual(typeof callback, 'function');
database.users.list(function (error, result) {
if (error) return callback(error);
// skip users without a github token
var users = result.filter(function (u) { return !!u.githubToken; });
async.each(users, function (user, callback) {
syncStarredByUser(user, function (error) {
async.each(result, function (user, callback) {
// errors are ignored here
syncGithubStarredByUser(user, function (error) {
if (error) console.error(error);
// errors are ignored here
callback();
});
}, callback);
});
}
function syncStarredByUser(user, callback) {
function syncGithubStarredByUser(user, callback) {
assert.strictEqual(typeof user, 'object');
assert.strictEqual(typeof callback, 'function');
if (!user.githubToken) return callback();
debug('syncGithubStarredByUser: ', user.id)
github.getStarred(user.githubToken, function (error, result) {
if (error) return callback(error);
// translate from github to internal model
var starredProjects = result.map(function (p) { return { name: p.full_name }; });
database.projects.list(user.id, function (error, trackedProjects) {
database.projects.listByType(user.id, database.PROJECT_TYPE_GITHUB, function (error, trackedProjects) {
if (error) return callback(error);
var newProjects = starredProjects.filter(function (a) { return !trackedProjects.find(function (b) { return a.name === b.name; }); });
......@@ -98,7 +99,7 @@ function syncStarredByUser(user, callback) {
// do not overwhelm github api with async.each() we hit rate limits if we do
async.eachSeries(newProjects, function (project, callback) {
debug(`syncStarredByUser: [${project.name}] is new for user ${user.id}`);
debug(`syncGithubStarredByUser: [${project.name}] is new for user ${user.id}`);
// we add projects first with release notification disabled
database.projects.add({ type: database.PROJECT_TYPE_GITHUB, userId: user.id, name: project.name }, function (error, result) {
......@@ -111,7 +112,7 @@ function syncStarredByUser(user, callback) {
if (error) return callback(error);
async.each(outdatedProjects, function (project, callback) {
debug(`syncStarredByUser: [${project.name}] not starred anymore by ${user.id}`);
debug(`syncGithubStarredByUser: [${project.name}] not starred anymore by ${user.id}`);
database.projects.remove(project.id, callback);
}, function (error) {
......@@ -129,9 +130,19 @@ function syncReleasesByProject(user, project, callback) {
assert.strictEqual(typeof project, 'object');
assert.strictEqual(typeof callback, 'function');
debug(`syncReleasesByProject: [${project.name}] start sync releases. Last successful sync was at`, new Date(project.lastSuccessfulSyncAt));
debug(`syncReleasesByProject: [${project.name}] type ${project.type} start sync releases. Last successful sync was at`, new Date(project.lastSuccessfulSyncAt));
var api;
if (project.type === database.PROJECT_TYPE_GITHUB) {
api = github;
} else if (project.type === database.PROJECT_TYPE_GITLAB) {
api = gitlab;
} else {
debug(`syncReleasesByProject: [${project.name}] unknown type ${project.type}. Ignoring for now`);
return callback();
}
github.getReleases(user.githubToken, project, function (error, result) {
api.getReleases(user.githubToken, project, function (error, result) {
if (error) return callback(error);
// map to internal model
......@@ -178,11 +189,6 @@ function syncReleasesByUser(user, callback) {
database.projects.list(user.id, function (error, result) {
if (error) return callback(error);
if (result.type !== database.PROJECT_TYPE_GITHUB) {
debug(`syncReleasesByUser: ignoring ${result.name} of type ${result.type} for now`);
return callback();
}
async.eachSeries(result, function (project, callback) {
syncReleasesByProject(user, project, callback);
}, function (error) {
......@@ -198,10 +204,7 @@ function syncReleases(callback) {
database.users.list(function (error, result) {
if (error) return callback(error);
// skip users without a github token
var users = result.filter(function (u) { return !!u.githubToken; });
async.eachSeries(users, function (user, callback) {
async.eachSeries(result, function (user, callback) {
syncReleasesByUser(user, function (error) {
if (error) console.error(error);
......
......@@ -3,7 +3,7 @@
/* global Vue */
/* global superagent */
var DEFAULT_VIEW = 'welcome';
var DEFAULT_VIEW = 'projectAdd';
new Vue({
el: '#app',
......
'use strict';
var async = require('async');
exports.up = function(db, callback) {
async.series([
db.runSql.bind(db, 'ALTER TABLE projects ADD COLUMN type VARCHAR(32) NOT NULL DEFAULT "github"'),
db.runSql.bind(db, 'ALTER TABLE projects MODIFY COLUMN type VARCHAR(32)')
], callback)
};
exports.down = function(db, callback) {
db.runSql('ALTER TABLE projects DROP COLUMN type', callback);
};
......@@ -36,6 +36,11 @@
"lodash": "^4.14.0"
}
},
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
},
"axios": {
"version": "0.19.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.19.0.tgz",
......@@ -125,12 +130,25 @@
"resolved": "https://registry.npmjs.org/colors/-/colors-1.2.4.tgz",
"integrity": "sha512-6Y+iBnWmXL+AWtlOp2Vr6R2w5MUlNJRwR0ShVFaAb1CqWzhPOpQg4L0jxD+xpw/Nc8QJwaq3KM79QUCriY8CWQ=="
},
"combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"requires": {
"delayed-stream": "~1.0.0"
}
},
"commander": {
"version": "2.20.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz",
"integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==",
"optional": true
},
"component-emitter": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
"integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg=="
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
......@@ -196,6 +214,11 @@
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
},
"cookiejar": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz",
"integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA=="
},
"core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
......@@ -286,6 +309,11 @@
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.5.1.tgz",
"integrity": "sha512-N8vBdOa+DF7zkRrDCsaOXoCs/E2fJfx9B9MrKnnSiHNh4ws7eSys6YQE4KvT1cecKmOASYQBhbKjeuDD9lT81w=="
},
"delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
},
"depd": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
......@@ -387,6 +415,11 @@
"resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz",
"integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A="
},
"fast-safe-stringify": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz",
"integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA=="
},
"final-fs": {
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/final-fs/-/final-fs-1.6.1.tgz",
......@@ -428,6 +461,21 @@
"debug": "=3.1.0"
}
},
"form-data": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz",
"integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==",
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
}
},
"formidable": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz",
"integrity": "sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q=="
},
"forwarded": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
......@@ -1091,6 +1139,77 @@
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
"integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo="
},
"superagent": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/superagent/-/superagent-5.2.2.tgz",
"integrity": "sha512-pMWBUnIllK4ZTw7p/UaobiQPwAO5w/1NRRTDpV0FTVNmECztsxKspj3ZWEordVEaqpZtmOQJJna4yTLyC/q7PQ==",
"requires": {
"component-emitter": "^1.3.0",
"cookiejar": "^2.1.2",
"debug": "^4.1.1",
"fast-safe-stringify": "^2.0.7",
"form-data": "^3.0.0",
"formidable": "^1.2.1",
"methods": "^1.1.2",
"mime": "^2.4.4",
"qs": "^6.9.1",
"readable-stream": "^3.4.0",
"semver": "^6.3.0"
},
"dependencies": {
"debug": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"requires": {
"ms": "^2.1.1"
}
},
"mime": {
"version": "2.4.4",
"resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",
"integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA=="
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"qs": {
"version": "6.9.3",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.9.3.tgz",
"integrity": "sha512-EbZYNarm6138UKKq46tdx08Yo/q9ZhFoAXAI1meAFd2GtbRDhbZY2WQSICskT0c5q99aFzLG1D4nvTk9tqfXIw=="
},
"readable-stream": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
"requires": {
"inherits": "^2.0.3",
"string_decoder": "^1.1.1",
"util-deprecate": "^1.0.1"
}
},
"safe-buffer": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
"integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg=="
},
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
},
"string_decoder": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
"requires": {
"safe-buffer": "~5.2.0"
}
}
}
},
"supererror": {
"version": "0.7.2",
"resolved": "https://registry.npmjs.org/supererror/-/supererror-0.7.2.tgz",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment