From c0f87172fab63d9410fe1db52fcd2e0ab41bf41c Mon Sep 17 00:00:00 2001 From: ikisialeu <36271792+ikisialeu@users.noreply.github.com> Date: Mon, 12 Mar 2018 06:24:45 +0300 Subject: [PATCH] fix: validate timezones (#1638) `Adds a config validation check for timezone, checking it against the list in moment-timezome.js`. Configs with invalid timezones will raise a configuration error. Closes #1483 --- lib/config/validation.js | 13 ++++++++++++- lib/workers/branch/schedule.js | 14 +++++++++++++- test/config/__snapshots__/validation.spec.js.snap | 4 ++++ test/config/validation.spec.js | 4 +++- test/workers/branch/schedule.spec.js | 14 ++++++++++++++ 5 files changed, 46 insertions(+), 3 deletions(-) diff --git a/lib/config/validation.js b/lib/config/validation.js index e0fe44d25e..1186a3ac27 100644 --- a/lib/config/validation.js +++ b/lib/config/validation.js @@ -1,6 +1,9 @@ const semver = require('semver'); const options = require('./definitions').getOptions(); -const { hasValidSchedule } = require('../workers/branch/schedule'); +const { + hasValidSchedule, + hasValidTimezone, +} = require('../workers/branch/schedule'); let optionTypes; @@ -61,6 +64,14 @@ function validateConfig(config) { message: `Invalid schedule: \`${errorMessage}\``, }); } + } else if (key === 'timezone' && val !== null) { + const [validTimezone, errorMessage] = hasValidTimezone(val); + if (!validTimezone) { + errors.push({ + depName: 'Configuration Error', + message: errorMessage, + }); + } } else if (key === 'allowedVersions' && val !== null) { if (!semver.validRange(val)) { errors.push({ diff --git a/lib/workers/branch/schedule.js b/lib/workers/branch/schedule.js index cf01df4c05..714de6d3e0 100644 --- a/lib/workers/branch/schedule.js +++ b/lib/workers/branch/schedule.js @@ -2,6 +2,7 @@ const later = require('later'); const moment = require('moment-timezone'); module.exports = { + hasValidTimezone, hasValidSchedule, isScheduledNow, }; @@ -10,6 +11,13 @@ function fixShortHours(input) { return input.replace(/( \d?\d)((a|p)m)/g, '$1:00$2'); } +function hasValidTimezone(timezone) { + if (!moment.tz.zone(timezone)) { + return [false, `Invalid timezone: ${timezone}`]; + } + return [true]; +} + function hasValidSchedule(schedule) { let message; // check if any of the schedules fail to parse @@ -69,7 +77,11 @@ function isScheduledNow(config) { logger.debug(`now=${now.format()}`); // Adjust the time if repo is in a different timezone to renovate if (config.timezone) { - // TODO: check for validity manually + const [validTimezone, error] = hasValidTimezone(config.timezone); + if (!validTimezone) { + logger.warn(error); + return true; + } now = now.tz(config.timezone); logger.debug(`now=${now.format()}`); } diff --git a/test/config/__snapshots__/validation.spec.js.snap b/test/config/__snapshots__/validation.spec.js.snap index fcc172e25b..bb96c609c0 100644 --- a/test/config/__snapshots__/validation.spec.js.snap +++ b/test/config/__snapshots__/validation.spec.js.snap @@ -14,6 +14,10 @@ Array [ "depName": "Configuration Error", "message": "Invalid schedule: \`Schedule \\"every 15 mins every weekday\\" should not specify minutes\`", }, + Object { + "depName": "Configuration Error", + "message": "Invalid timezone: Asia", + }, Object { "depName": "Configuration Error", "message": "Configuration option \`labels\` should be a list (Array)", diff --git a/test/config/validation.spec.js b/test/config/validation.spec.js index 3c2f725da2..bee1d24067 100644 --- a/test/config/validation.spec.js +++ b/test/config/validation.spec.js @@ -6,6 +6,7 @@ describe('config/validation', () => { const config = { foo: 1, schedule: ['after 5pm'], + timezone: 'Asia/Singapore', prBody: 'some-body', lockFileMaintenance: { bar: 2, @@ -21,6 +22,7 @@ describe('config/validation', () => { allowedVersions: 'foo', enabled: 1, schedule: ['every 15 mins every weekday'], + timezone: 'Asia', labels: 5, semanticCommitType: 7, lockFileMaintenance: false, @@ -32,7 +34,7 @@ describe('config/validation', () => { }; const { warnings, errors } = configValidation.validateConfig(config); expect(warnings).toHaveLength(0); - expect(errors).toHaveLength(7); + expect(errors).toHaveLength(8); expect(errors).toMatchSnapshot(); }); }); diff --git a/test/workers/branch/schedule.spec.js b/test/workers/branch/schedule.spec.js index 9bd78798ad..1f55a95435 100644 --- a/test/workers/branch/schedule.spec.js +++ b/test/workers/branch/schedule.spec.js @@ -2,6 +2,14 @@ const mockDate = require('mockdate'); const schedule = require('../../../lib/workers/branch/schedule'); describe('workers/branch/schedule', () => { + describe('hasValidTimezone(schedule)', () => { + it('returns false for invalid timezone', () => { + expect(schedule.hasValidTimezone('Asia')[0]).toBe(false); + }); + it('returns true for valid timezone', () => { + expect(schedule.hasValidTimezone('Asia/Singapore')[0]).toBe(true); + }); + }); describe('hasValidSchedule(schedule)', () => { beforeEach(() => { jest.resetAllMocks(); @@ -91,6 +99,12 @@ describe('workers/branch/schedule', () => { const res = schedule.isScheduledNow(config); expect(res).toBe(true); }); + it('returns true if invalid timezone', () => { + config.schedule = ['after 4:00pm']; + config.timezone = 'Asia'; + const res = schedule.isScheduledNow(config); + expect(res).toBe(true); + }); it('supports before hours true', () => { config.schedule = ['before 4:00pm']; const res = schedule.isScheduledNow(config); -- GitLab