From ff8c3bbc65878998d5817109ae8cd51d9a968e6b Mon Sep 17 00:00:00 2001 From: Ken Perkins Date: Mon, 4 May 2020 17:31:06 -0700 Subject: [PATCH] Add support for supplying multiple label files - Fixes #49 This change introduces support for any number of `--labels` arguments to be supplied. The behavior is the same as before, with regards to http(s) urls or local paths, and after they are all collected, they will be merged. Any items with a duplicate name and different property values will throw an error. Otherwise they will be merged and then applied. --- bin/github-label-sync.js | 87 ++++++++++++++++++++++++++++++---------- 1 file changed, 66 insertions(+), 21 deletions(-) diff --git a/bin/github-label-sync.js b/bin/github-label-sync.js index aaee156..087b1a8 100755 --- a/bin/github-label-sync.js +++ b/bin/github-label-sync.js @@ -19,7 +19,8 @@ program .option( '-l, --labels ', 'the path or URL to look for the label configuration in. Default: labels.json', - 'labels.json' + getLabelFiles, + [ ] ) .option( '-d, --dry-run', @@ -41,29 +42,44 @@ if (program.args.length !== 1) { program.help(); } +function getLabelFiles(value, previous) { + return previous.concat([value]); +} + function readLabels() { - if (program.labels.indexOf('http://') === 0 || program.labels.indexOf('https://') === 0) { - const got = require('got'); + if (program.labels.length === 0) { + program.labels = [ 'labels.json' ]; + } - return got(program.labels, { json: true }).then((response) => response.body).catch(() => { - console.error(chalk.red(`Downloading labels from ${program.labels} failed`)); - process.exit(1); - }); + const files = []; - } else { - // Resolve the label configuration path - if (!/^[\/\~]/.test(program.labels)) { - program.labels = path.resolve(process.cwd(), program.labels); - } + program.labels.forEach((file) => { + if (file.indexOf('http://') === 0 || file.indexOf('https://') === 0) { + const got = require('got'); - // Load the labels - try { - return Promise.resolve(require(program.labels)); - } catch (error) { - console.error(chalk.red(`No labels were found in ${program.labels}`)); - process.exit(1); + files.push(got(file, { json: true }).then((response) => response.body).catch(() => { + console.error(chalk.red(`Downloading labels from ${file} failed`)); + process.exit(1); + })); + + } else { + // Resolve the label configuration path + if (!/^[\/\~]/.test(file)) { + file = path.resolve(process.cwd(), file); + } + + // Load the labels + try { + files.push(Promise.resolve(require(file))); + } catch (error) { + console.error(chalk.red(`No labels were found in ${file}`)); + process.exit(1); + } } - } + + }); + + return Promise.all(files); } // Apply some log formatting @@ -79,16 +95,45 @@ const format = { } }; +// Merge our lists together +function merge(files) { + const data = {}; + const labels = []; + + files.forEach((file) => { + if (!Array.isArray(file)) { + return; + } + + file.forEach((label) => { + if (data[label.name] !== null && data[label.name] !== '') { + data[label.name] = label; + } else { + if (JSON.stringify(data[label.name]) !== JSON.stringify(label)) { + console.error(chalk.red(`Conflicting label names were found: ${label.name}`)); + process.exit(1); + } + } + }); + }); + + Object.keys(data).forEach((key) => { + labels.push(data[key]); + }); + + return labels; +} + // Pull together all the options function resolveOptions() { - return readLabels().then((labels) => { + return readLabels().then((files) => { return { accessToken: program.accessToken, allowAddedLabels: program.allowAddedLabels, dryRun: program.dryRun, endpoint: program.endpoint, format: format, - labels: labels, + labels: merge(files), log: console, repo: program.args[0] };