Repository: release-drafter/release-drafter
Pull request #338 (2019-12-23 13:03:23)

Put config in seperate module
I put all things related to config in a separate module to make the entry file of the app more readable. I've also added tests to make sure it works as intended.

casz: This will conflict somewhat with #193 

Patch:
diff --git a/index.js b/index.js
index cd9d161..b743ff6 100644
--- a/index.js
+++ b/index.js
@@ -1,44 +1,18 @@
-const getConfig = require('probot-config')
+const { getConfig } = require('./lib/config')
 const { isTriggerableBranch } = require('./lib/triggerable-branch')
 const { findReleases, generateReleaseInfo } = require('./lib/releases')
 const { findCommitsWithAssociatedPullRequests } = require('./lib/commits')
-const { validateReplacers } = require('./lib/template')
-const core = require('@actions/core')
-const {
-  validateSortBy,
-  validateSortDirection,
-  sortPullRequests,
-  SORT_BY,
-  SORT_DIRECTIONS
-} = require('./lib/sort-pull-requests')
+const { sortPullRequests } = require('./lib/sort-pull-requests')
 const log = require('./lib/log')
-
-const configName = 'release-drafter.yml'
+const core = require('@actions/core')
 
 module.exports = app => {
   app.on('push', async context => {
-    const defaults = {
-      branches: context.payload.repository.default_branch,
-      'change-template': `* $TITLE (#$NUMBER) @$AUTHOR`,
-      'no-changes-template': `* No changes`,
-      'version-template': `$MAJOR.$MINOR.$PATCH`,
-      categories: [],
-      'exclude-labels': [],
-      replacers: [],
-      'sort-by': SORT_BY.mergedAt,
-      'sort-direction': SORT_DIRECTIONS.descending
-    }
-    const config = Object.assign(
-      defaults,
-      (await getConfig(context, configName)) || {}
-    )
-    config.replacers = validateReplacers({
+    const config = await getConfig({
       app,
       context,
-      replacers: config.replacers
+      getConfig: require('probot-config')
     })
-    config['sort-by'] = validateSortBy(config['sort-by'])
-    config['sort-direction'] = validateSortDirection(config['sort-direction'])
 
     // GitHub Actions merge payloads slightly differ, in that their ref points
     // to the PR branch instead of refs/heads/master
diff --git a/lib/config.js b/lib/config.js
new file mode 100644
index 0000000..2211cbf
--- /dev/null
+++ b/lib/config.js
@@ -0,0 +1,46 @@
+const {
+  SORT_DIRECTIONS,
+  validateSortDirection
+} = require('./sort-pull-requests')
+const { validateReplacers } = require('./template')
+
+const CONFIG_NAME = 'release-drafter.yml'
+
+const DEFAULT_CONFIG = Object.freeze({
+  'change-template': `* $TITLE (#$NUMBER) @$AUTHOR`,
+  'no-changes-template': `* No changes`,
+  'version-template': `$MAJOR.$MINOR.$PATCH`,
+  categories: [],
+  'exclude-labels': [],
+  replacers: [],
+  'sort-direction': SORT_DIRECTIONS.descending
+})
+
+module.exports.DEFAULT_CONFIG = DEFAULT_CONFIG
+
+module.exports.getConfig = async function getConfig({
+  app,
+  context,
+  getConfig: fetchConfig
+}) {
+  const defaults = {
+    ...DEFAULT_CONFIG,
+    branches: context.payload.repository.default_branch
+  }
+
+  const config = await fetchConfig(context, CONFIG_NAME, defaults)
+
+  try {
+    config.replacers = validateReplacers({
+      app,
+      context,
+      replacers: config.replacers
+    })
+  } catch (error) {
+    config.replacers = []
+  }
+
+  config['sort-direction'] = validateSortDirection(config['sort-direction'])
+
+  return config
+}


Test patch:
diff --git a/test/config.test.js b/test/config.test.js
new file mode 100644
index 0000000..722d5d0
--- /dev/null
+++ b/test/config.test.js
@@ -0,0 +1,86 @@
+const { getConfig, DEFAULT_CONFIG } = require('../lib/config')
+const { SORT_DIRECTIONS } = require('../lib/sort-pull-requests')
+
+function createGetConfigMock(config) {
+  return (context, configName, defaults) =>
+    Promise.resolve({ ...defaults, ...config })
+}
+
+describe('getConfig', () => {
+  it('returns defaults', async () => {
+    const app = { log: jest.fn() }
+    const context = {
+      payload: { repository: { default_branch: '' } }
+    }
+
+    const config = await getConfig({
+      app,
+      context,
+      getConfig: createGetConfigMock({})
+    })
+
+    expect(config).toEqual({ ...DEFAULT_CONFIG, branches: expect.any(String) })
+  })
+
+  describe('`replacers` option', () => {
+    it('validates `replacers` option', async () => {
+      const app = { log: jest.fn() }
+      const context = { payload: { repository: { default_branch: '' } } }
+
+      const config = await getConfig({
+        app,
+        context,
+        getConfig: createGetConfigMock({ replacers: 'bogus' })
+      })
+
+      expect(config['replacers']).toEqual([])
+    })
+
+    it('accepts valid `replacers`', async () => {
+      const app = { log: jest.fn() }
+      const context = { payload: { repository: { default_branch: '' } } }
+
+      const config = await getConfig({
+        app,
+        context,
+        getConfig: createGetConfigMock({
+          replacers: [{ search: 'search', replace: 'replace' }]
+        })
+      })
+
+      expect(config['replacers']).toEqual([
+        { search: expect.any(RegExp), replace: 'replace' }
+      ])
+    })
+  })
+
+  describe('`sort-direction` option', () => {
+    it('validates `sort-direction` option', async () => {
+      const app = { log: jest.fn() }
+      const context = { payload: { repository: { default_branch: '' } } }
+
+      const config = await getConfig({
+        app,
+        context,
+        getConfig: createGetConfigMock({ 'sort-direction': 'bogus' })
+      })
+
+      expect(config['sort-direction']).toBe(SORT_DIRECTIONS.descending)
+    })
+
+    it('accepts a valid `sort-direction`', async () => {
+      const app = { log: jest.fn() }
+      const context = { payload: { repository: { default_branch: '' } } }
+
+      const config = await getConfig({
+        app,
+        context,
+        getConfig: createGetConfigMock({
+          'sort-direction': SORT_DIRECTIONS.ascending
+        })
+      })
+
+      expect(config['sort-direction']).toBe(SORT_DIRECTIONS.ascending)
+    })
+  })
+})