From 8e159fbbb513ce5d9b74b7b886f9f38c45708ae1 Mon Sep 17 00:00:00 2001 From: maccyber Date: Mon, 31 Oct 2016 17:17:20 +0100 Subject: [PATCH] Adds new tests --- README.md | 3 +- handlers/index.js | 42 ++++++---- lib/run-script.js | 3 +- package.json | 7 +- plugins/index.js | 4 +- test/test-config.js | 9 ++ test/test-dockerhub-callback.js | 44 ++++++++++ test/test-routes.js | 66 +++++++++++++++ test/test-run-script.js | 39 +++++++++ test/test.js | 144 -------------------------------- 10 files changed, 193 insertions(+), 168 deletions(-) create mode 100644 test/test-config.js create mode 100644 test/test-dockerhub-callback.js create mode 100644 test/test-routes.js create mode 100644 test/test-run-script.js delete mode 100644 test/test.js diff --git a/README.md b/README.md index ca7954d..bcb2f8e 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,11 @@ [![Build Status](https://travis-ci.org/maccyber/dockerhub-webhook.svg?branch=master)](https://travis-ci.org/maccyber/dockerhub-webhook) [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](https://github.com/feross/standard) [![Coverage Status](https://coveralls.io/repos/github/maccyber/dockerhub-webhook/badge.svg)](https://coveralls.io/github/maccyber/dockerhub-webhook) +[![Code Climate](https://codeclimate.com/github/maccyber/dockerhub-webhook/badges/gpa.svg)](https://codeclimate.com/github/maccyber/dockerhub-webhook) # dockerhub-webhook -Automatic [Docker](https://www.docker.com) deployment with [Webhooks](https://docs.docker.com/docker-hub/builds/#webhooks). +Automatic [Docker](https://www.docker.com) deployment with [Webhooks](https://docs.docker.com/docker-hub/builds/#webhooks) written in [NodeJS](https://nodejs.org). dockerhub-webhook listens to incoming HTTP POST-requests from hub.docker.com and triggers your specified script(s). diff --git a/handlers/index.js b/handlers/index.js index 9cdb728..5a5b35d 100644 --- a/handlers/index.js +++ b/handlers/index.js @@ -2,30 +2,38 @@ const config = require('../config') const runScript = require('../lib/run-script') +const Boom = require('boom') module.exports = (request, reply) => { const hooks = require('../scripts') const token = request.params.token const payload = request.payload - if (token === config.token && payload && payload.repository && payload.repository.name) { + let err + + if (token !== config.token) { + err = 'Invalid token' + } else if (!payload) { + err = 'Missing payload' + } else if (!payload.repository) { + err = 'Missing payload.repository' + } else if (!payload.repository.name) { + err = 'Missing payload.repository.name' + } else if (!hooks[payload.repository.name]) { + err = `${payload.repository.name} does not exist in scripts/index.js` + } + if (err) { + request.log(['debug'], err) + reply(Boom.badRequest(err)) + } else { request.log(['debug'], 'Payload from docker hub:') request.log(['debug'], payload) - const repo = payload.repository.name - if (hooks[repo]) { - request.log(['debug'], `Updating repo: ${repo}`) - const options = { - script: hooks[repo], - callbackUrl: payload.callback_url, - request: request - } - reply(repo).code(204) - runScript(options) - } else { - request.log(['debug'], `${repo} does not exist in scripts/index.js`) - reply().code(404) + request.log(['debug'], `Updating repo: ${payload.repository.name}`) + const options = { + script: hooks[payload.repository.name], + callbackUrl: payload.callback_url, + request: request } - } else { - request.log(['debug'], 'Invalid token or dockerhub JSON') - reply().code(404) + reply(payload.repository.name).code(204) + runScript(options) } } diff --git a/lib/run-script.js b/lib/run-script.js index f4a2869..3fbde8e 100644 --- a/lib/run-script.js +++ b/lib/run-script.js @@ -3,6 +3,7 @@ const path = require('path') const fileExists = require('file-exists') const dockerhubCallback = require('./dockerhub-callback') +const exec = require('child_process').exec module.exports = (options) => { if (!options) { @@ -15,8 +16,6 @@ module.exports = (options) => { return new Error('Missing required input: options.script') } const request = options.request - const exec = require('child_process').exec - const cmd = path.resolve('scripts/' + options.script) if (!fileExists(cmd)) { request.log(['debug'], `File: ${cmd} does not exist`) diff --git a/package.json b/package.json index c3b3add..781608e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dockerhub-webhook", - "version": "2.0.1", + "version": "2.0.3", "description": "Docker hub webhook", "license": "MIT", "author": { @@ -46,10 +46,11 @@ "tap": "8.0.0" }, "dependencies": { + "boom": "4.2.0", "file-exists": "2.0.0", "good": "7.0.2", - "good-console": "^6.3.1", - "good-squeeze": "^5.0.0", + "good-console": "6.3.1", + "good-squeeze": "5.0.0", "hapi": "15.2.0", "joi": "9.2.0", "request": "2.76.0" diff --git a/plugins/index.js b/plugins/index.js index 8f8cd7c..38f755e 100644 --- a/plugins/index.js +++ b/plugins/index.js @@ -1,5 +1,7 @@ 'use strict' +const good = require('good') + const goodOptions = { ops: { interval: 900000 @@ -17,7 +19,7 @@ const goodOptions = { module.exports = [ { - register: require('good'), + register: good, options: goodOptions } ] diff --git a/test/test-config.js b/test/test-config.js new file mode 100644 index 0000000..0a4c10a --- /dev/null +++ b/test/test-config.js @@ -0,0 +1,9 @@ +'use strict' + +const tap = require('tap') +const config = require('../config') + +tap.equal(config.port, 3000, 'Default server port ok') +tap.equal(config.route, '/api', 'Default route ok') +tap.equal(config.token, 'abc123', 'Default token ok') + diff --git a/test/test-dockerhub-callback.js b/test/test-dockerhub-callback.js new file mode 100644 index 0000000..94a54c0 --- /dev/null +++ b/test/test-dockerhub-callback.js @@ -0,0 +1,44 @@ +'use strict' + +const tap = require('tap') +const dockerhubCallback = require('../lib/dockerhub-callback') + +tap.test('dockerhubCallback missing options', (t) => { + const options = false + dockerhubCallback(options, (err) => { + t.equal(err.message, 'Missing required input: options', 'Missing options ok') + t.end() + }) +}) + +tap.test('dockerhubCallback missing options.callbackUrl', (t) => { + const options = {} + dockerhubCallback(options, (err) => { + t.equal(err.message, 'Missing required input: options.callbackUrl', 'Missing options.callbackUrl ok') + t.end() + }) +}) + +tap.test('dockerhubCallback invalid URI', (t) => { + const options = { + callbackUrl: 'wrongurl' + } + dockerhubCallback(options, (err) => { + t.equal(err.message, `Invalid URI "${options.callbackUrl}"`, 'Wrong URL ok') + t.end() + }) +}) + +tap.test('dockerhubCallback', (t) => { + const options = { + callbackUrl: 'https://maccyber.io/api/test' + } + dockerhubCallback(options, (err, data) => { + if (err) { + throw err + } + t.equal(data.text, `Callback sent to ${options.callbackUrl}`, 'dockerhubCallback ok') + t.equal(data.response.test, 'ok', 'dockerhubCallback response ok') + t.end() + }) +}) diff --git a/test/test-routes.js b/test/test-routes.js new file mode 100644 index 0000000..a874875 --- /dev/null +++ b/test/test-routes.js @@ -0,0 +1,66 @@ +'use strict' + +const tap = require('tap') +const Hapi = require('hapi') +const config = require('../config') +const routes = require('../routes') + +const server = new Hapi.Server() +server.connection() +server.route(routes) + +tap.test('GET /', (t) => { + server.inject('/', (res) => { + t.equal(res.statusCode, 200, 'Status code ok') + t.equal(res.result.message, '(Nothing but) Flowers', 'Message ok') + t.end() + }) +}) + +tap.test('Not found', (t) => { + const route = `/wrongroute` + server.inject(route, (res) => { + t.equal(res.statusCode, 404, '404 returned OK') + t.end() + }) +}) + +tap.test('Invalid token or dockerhub JSON', (t) => { + const options = { + method: 'POST', + url: `${config.route}/${config.token}`, + payload: {} + } + server.inject(options, (res) => { + t.equal(res.statusCode, 400, 'Invalid token or dockerhub JSON ok') + t.end() + }) +}) + +tap.test('does not exist in scripts/index.js', (t) => { + const file = require('./data/dockerhub.json') + file.repository.name = 'wrong' + const options = { + method: 'POST', + url: `${config.route}/${config.token}`, + payload: file + } + server.inject(options, (res) => { + t.equal(res.statusCode, 400, 'Repo is not configured config ok') + t.end() + }) +}) + +tap.test('Valid dockerhub JSON', (t) => { + const file = require('./data/dockerhub.json') + file.repository.name = 'testhook' + const options = { + method: 'POST', + url: `${config.route}/${config.token}`, + payload: file + } + server.inject(options, (res) => { + t.equal(res.statusCode, 204, 'Valid dockerhub JSON ok') + t.end() + }) +}) diff --git a/test/test-run-script.js b/test/test-run-script.js new file mode 100644 index 0000000..2127b9e --- /dev/null +++ b/test/test-run-script.js @@ -0,0 +1,39 @@ +'use strict' + +const tap = require('tap') +const Hapi = require('hapi') +const runScript = require('../lib/run-script') +const server = new Hapi.Server() + +tap.test('runScript missing options', (t) => { + const options = false + const result = runScript(options) + t.equal(result.message, 'Missing required input: options', 'runScript missing options ok') + t.end() +}) + +tap.test('runScript missing options.request', (t) => { + const options = {} + const result = runScript(options) + t.equal(result.message, 'Missing required input: options.request', 'runScript missing options.request ok') + t.end() +}) + +tap.test('runScript missing options.script', (t) => { + const options = { + request: server + } + const result = runScript(options) + t.equal(result.message, 'Missing required input: options.script', 'runScript missing options.script ok') + t.end() +}) + +tap.test('runScript script do not exist', (t) => { + const options = { + request: server, + script: 'dengalevandrer' + } + const result = runScript(options) + t.match(result.message, 'does not exist', 'runScript script do not exist ok') + t.end() +}) diff --git a/test/test.js b/test/test.js deleted file mode 100644 index 04c4b6b..0000000 --- a/test/test.js +++ /dev/null @@ -1,144 +0,0 @@ -const tap = require('tap') -const Hapi = require('hapi') -const config = require('../config') -const routes = require('../routes') -const dockerhubCallback = require('../lib/dockerhub-callback') -const runScript = require('../lib/run-script') - -const server = new Hapi.Server() -server.connection() -server.route(routes) - -tap.equal(config.port, 3000, 'Default server port ok') -tap.equal(config.route, '/api', 'Default route ok') -tap.equal(config.token, 'abc123', 'Default token ok') - -tap.test('GET /', (t) => { - server.inject('/', (res) => { - tap.equal(res.statusCode, 200, 'Status code ok') - tap.equal(res.result.message, '(Nothing but) Flowers', 'Message ok') - t.end() - }) -}) - -tap.test('Not found', (t) => { - const route = `${config.route}/${config.token}` - server.inject(route, (res) => { - tap.equal(res.statusCode, 404, '404 returned OK') - t.end() - }) -}) - -tap.test('Invalid token or dockerhub JSON', (t) => { - const options = { - method: 'POST', - url: `${config.route}/${config.token}`, - payload: {} - } - server.inject(options, (res) => { - tap.equal(res.statusCode, 404, 'Invalid token or dockerhub JSON ok') - t.end() - }) -}) - -tap.test('does not exist in scripts/index.js', (t) => { - const file = require('./data/dockerhub.json') - file.repository.name = 'wrong' - const options = { - method: 'POST', - url: `${config.route}/${config.token}`, - payload: file - } - server.inject(options, (res) => { - tap.equal(res.statusCode, 404, 'Repo is not configured config ok') - t.end() - }) -}) - -tap.test('Valid dockerhub JSON', (t) => { - const file = require('./data/dockerhub.json') - file.repository.name = 'testhook' - const options = { - method: 'POST', - url: `${config.route}/${config.token}`, - payload: file - } - server.inject(options, (res) => { - tap.equal(res.statusCode, 204, 'Valid dockerhub JSON ok') - t.end() - }) -}) - -tap.test('dockerhubCallback missing options', (t) => { - const options = false - dockerhubCallback(options, (err) => { - tap.equal(err.message, 'Missing required input: options', 'Missing options ok') - t.end() - }) -}) - -tap.test('dockerhubCallback missing options.callbackUrl', (t) => { - const options = {} - dockerhubCallback(options, (err) => { - tap.equal(err.message, 'Missing required input: options.callbackUrl', 'Missing options.callbackUrl ok') - t.end() - }) -}) - -tap.test('dockerhubCallback invalid URI', (t) => { - const options = { - callbackUrl: 'wrongurl' - } - dockerhubCallback(options, (err) => { - tap.equal(err.message, `Invalid URI "${options.callbackUrl}"`, 'Wrong URL ok') - t.end() - }) -}) - -tap.test('dockerhubCallback', (t) => { - const options = { - callbackUrl: 'https://maccyber.io/api/test' - } - dockerhubCallback(options, (err, data) => { - if (err) { - throw err - } - tap.equal(data.text, `Callback sent to ${options.callbackUrl}`, 'dockerhubCallback ok') - tap.equal(data.response.test, 'ok', 'dockerhubCallback response ok') - t.end() - }) -}) - -tap.test('runScript missing options', (t) => { - const options = false - const result = runScript(options) - tap.equal(result.message, 'Missing required input: options', 'runScript missing options ok') - t.end() -}) - -tap.test('runScript missing options.request', (t) => { - const options = {} - const result = runScript(options) - tap.equal(result.message, 'Missing required input: options.request', 'runScript missing options.request ok') - t.end() -}) - -tap.test('runScript missing options.script', (t) => { - const options = { - request: server - } - const result = runScript(options) - tap.equal(result.message, 'Missing required input: options.script', 'runScript missing options.script ok') - t.end() -}) - -tap.test('runScript script do not exist', (t) => { - const options = { - request: server, - script: 'dengalevandrer' - } - const result = runScript(options) - tap.match(result.message, 'does not exist', 'runScript script do not exist ok') - t.end() -}) -