Skip to content

Commit

Permalink
feat(app): validate { name, columns } config
Browse files Browse the repository at this point in the history
Closes #39
  • Loading branch information
nikku committed Jul 29, 2019
1 parent 910308c commit a943d8c
Show file tree
Hide file tree
Showing 5 changed files with 220 additions and 63 deletions.
63 changes: 54 additions & 9 deletions packages/app/bin/run.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ const log = wrapLogger(logger, logger).child({
name: 'wuffle:run'
});

const Columns = require('../lib/columns');

const { version } = require('../package');

const NODE_ENV = process.env.NODE_ENV || 'development';
Expand All @@ -19,6 +21,14 @@ const IS_PROD = NODE_ENV === 'production';
const IS_DEV = NODE_ENV === 'development';


// shim

if (typeof Array.prototype.flat !== 'function') {
Array.prototype.flat = function() {
return Array.prototype.concat.call(this, ...this);
};
}

async function validate() {

log.info('Validating configuration');
Expand All @@ -33,7 +43,7 @@ async function validate() {
checkEnv('BASE_URL', IS_PROD),
checkConfig(),
checkBaseUrl()
].filter(problem => problem);
].flat().filter(problem => problem);

function isFatal(problem) {
return problem.type === 'ERROR';
Expand All @@ -58,27 +68,62 @@ async function validate() {
}
}

function checkConfigName(config) {
const problem = IS_PROD ? error : warning;

if (!config.name) {
return problem('missing config.name');
}
}

function checkConfigColumns(config) {

if (!config.columns) {
return error('missing config.columns');
}

try {
new Columns(config.columns);
} catch (error) {
// always an error, regardless of PROD / DEV
return error(error.message);
}
}

function checkConfigValues(config) {

return [
checkConfigName(config),
checkConfigColumns(config)
];

}

function checkConfig() {

const problem = IS_PROD ? error : warning;

let config;

if (process.env.BOARD_CONFIG) {
try {
JSON.parse(process.env.BOARD_CONFIG);

// we cool!
return;
config = JSON.parse(process.env.BOARD_CONFIG);
} catch (err) {
return problem(`Failed to parse env.BOARD_CONFIG as JSON: ${err.message}`);
}
}

try {
require('../wuffle.config.js');
} catch (err) {
return problem('Board not configured via env.BOARD_CONFIG or wuffle.config.js');
if (!config) {
try {
config = require('../wuffle.config.js');
} catch (err) {
return problem('Board not configured via env.BOARD_CONFIG or wuffle.config.js');
}
}

if (config) {
return checkConfigValues(config);
}
}

function checkEnv(key, isError=false) {
Expand Down
2 changes: 1 addition & 1 deletion packages/app/lib/apps/github-issues/GithubIssues.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ function GithubIssues(logger, config, columns) {

let update = {};

const newColumn = columns.findByName(newState);
const newColumn = columns.getByName(newState);

const issueState = newColumn.closed ? 'closed' : 'open';

Expand Down
111 changes: 90 additions & 21 deletions packages/app/lib/columns.js
Original file line number Diff line number Diff line change
@@ -1,33 +1,32 @@
const Types = {
const States = {
DEFAULT: 'DEFAULT',
IN_PROGRESS: 'IN_PROGRESS',
CLOSED: 'CLOSED',
PULL_REQUEST: 'PULL_REQUEST',
EXTERNAL_PULL_REQUEST: 'EXTERNAL_PULL_REQUEST'
IN_REVIEW: 'IN_REVIEW',
EXTERNAL_CONTRIBUTION: 'EXTERNAL_CONTRIBUTION'
};

const StateToNames = {
DEFAULT: 'Inbox',
IN_PROGRESS: 'In Progress',
CLOSED: 'Done',
IN_REVIEW: 'Needs Review',
EXTERNAL_CONTRIBUTION: 'Inbox'
};


class Columns {

constructor(columns) {
this.columns = columns;

this.columnsByLabel = columns.reduce((columnsByLabel, column) => {
if (column.label) {
columnsByLabel[column.label] = column;
}

return columnsByLabel;
}, {});
this.columnsByState = groupByStates(columns);

this.columnsByName = columns.reduce((columnsByName, column) => {
if (column.name) {
columnsByName[column.name] = column;
}
this.columnsByLabel = groupByLabel(columns);

return columnsByName;
}, {});
this.columnsByName = groupByName(columns);

this._getter = columnGetter(columns);
this._getter = createColumnGetter(columns);
}

getAll() {
Expand All @@ -38,12 +37,26 @@ class Columns {
return this._getter(issue);
}

findByName(columnName) {
getByName(columnName) {
return this.columnsByName[columnName];
}

getByState(state) {
if (state in States) {
const column = this.columnsByState[state];

if (!column) {
throw new Error('no column mapped to state <' + state + '>');
}

return column;
}

throw new Error('invalid state <' + state + '>');
}

isSorting(columnName) {
const column = this.findByName(columnName);
const column = this.getByName(columnName);

return column && column.sorting;
}
Expand All @@ -59,7 +72,9 @@ Columns.$inject = [ 'config.columns' ];
module.exports = Columns;


function columnGetter(columns) {
// helpers //////////////////

function createColumnGetter(columns) {

const sortedColumns = columns.slice().sort((a, b) => {
if (a.label && !b.label) {
Expand All @@ -70,7 +85,7 @@ function columnGetter(columns) {
});


const defaultColumn = columns.find(c => c.type === Types.DEFAULT) || columns[0];
const defaultColumn = columns.find(c => c.type === States.DEFAULT) || columns[0];

return function(issue) {

Expand All @@ -95,4 +110,58 @@ function columnGetter(columns) {

return (column || defaultColumn).name;
};
}

function groupByStates(columns) {
return Object.keys(States).reduce((columnsByState, state) => {

const defaultName = StateToNames[state];

const column = (
columns.find(c => c.name === defaultName)
);

if (!column) {
throw new Error('no column mapped to state: ' + state);
}

columnsByState[state] = column;

return columnsByState;
}, {});
}

function groupByLabel(columns) {
return columns.reduce((columnsByLabel, column) => {

const { label } = column;

if (label) {
if (columnsByLabel[label]) {
throw new Error('label already mapped to column: ' + label);
}

columnsByLabel[label] = column;
}

return columnsByLabel;
}, {});
}

function groupByName(columns) {
return columns.reduce((columnsByName, column) => {

const { name } = column;

if (name) {

if (columnsByName[name]) {
throw new Error('name already used: ' + name);
}

columnsByName[name] = column;
}

return columnsByName;
}, {});
}
5 changes: 3 additions & 2 deletions packages/app/lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,13 @@ module.exports = function(app) {

return events.emit('wuffle.pre-exit');
});
};
}

return setup().catch(
err => {
log.fatal('failed to create app', err);
process.exit(21)

process.exit(21);
}
);
};
Loading

0 comments on commit a943d8c

Please sign in to comment.