Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve error message for when config is not found #973

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 12 additions & 3 deletions dist/index.js
Expand Up @@ -405,7 +405,6 @@ module.exports.findCommitsWithAssociatedPullRequests = async ({

const core = __nccwpck_require__(42186)
const { validateSchema } = __nccwpck_require__(5171)
const { DEFAULT_CONFIG } = __nccwpck_require__(25586)
const log = __nccwpck_require__(13817)
const { runnerIsActions } = __nccwpck_require__(50918)
const Table = __nccwpck_require__(2101)
Expand All @@ -416,8 +415,16 @@ module.exports.getConfig = async function getConfig({ context, configName }) {
try {
const repoConfig = await context.config(
configName || DEFAULT_CONFIG_NAME,
DEFAULT_CONFIG
null
)
if (repoConfig == null) {
// noinspection ExceptionCaughtLocallyJS
throw new Error(
'Configuration file .github/' +
(configName || DEFAULT_CONFIG_NAME) +
' is not found. The configuration file must reside in your default branch.'
)
}

const config = validateSchema(context, repoConfig)

Expand All @@ -429,7 +436,9 @@ module.exports.getConfig = async function getConfig({ context, configName }) {
log({
context,
message:
'Config validation errors, please fix the following issues in release-drafter.yml:\n' +
'Config validation errors, please fix the following issues in ' +
(configName || DEFAULT_CONFIG_NAME) +
':\n' +
joiValidationErrorsAsTable(error),
})
}
Expand Down
15 changes: 12 additions & 3 deletions lib/config.js
@@ -1,6 +1,5 @@
const core = require('@actions/core')
const { validateSchema } = require('./schema')
const { DEFAULT_CONFIG } = require('./default-config')
const log = require('./log')
const { runnerIsActions } = require('./utils')
const Table = require('cli-table3')
Expand All @@ -11,8 +10,16 @@ module.exports.getConfig = async function getConfig({ context, configName }) {
try {
const repoConfig = await context.config(
configName || DEFAULT_CONFIG_NAME,
DEFAULT_CONFIG
null
)
if (repoConfig == null) {
// noinspection ExceptionCaughtLocallyJS
throw new Error(
'Configuration file .github/' +
(configName || DEFAULT_CONFIG_NAME) +
' is not found. The configuration file must reside in your default branch.'
)
}

const config = validateSchema(context, repoConfig)

Expand All @@ -24,7 +31,9 @@ module.exports.getConfig = async function getConfig({ context, configName }) {
log({
context,
message:
'Config validation errors, please fix the following issues in release-drafter.yml:\n' +
'Config validation errors, please fix the following issues in ' +
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the error relates to the file on the default branch, then this error message should mention that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is done exactly here:

if (repoConfig == null) {
const name = configName || DEFAULT_CONFIG_NAME
// noinspection ExceptionCaughtLocallyJS
throw new Error(
`Configuration file .github/${name} is not found. The configuration file must reside in your default branch.`
)
}

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's if it's missing.

If it's found and invalid, which branch did it read?

Copy link
Member

@jetersen jetersen Jan 16, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then joiValidationErrorsAsTable(error) will print out the errors?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But will it mention the branch?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't really know which "branch" as the config gets merged. So it could be in default branch or on the .github repo you need to fix the config.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah.

Could I convince you to reparse the configurations separately when you get an error? This wouldn't slow down the default path (beyond a slightly larger file), but would result in a much better user experience.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't want to create a custom version of https://github.com/probot/octokit-plugin-config to satisfy slightly better user experience. User should be able to comprehend release-drafter config setup. They are the once setting it up. You can keep it as simple as you want or as complex as you want.

Again potentially you could have endless _extends like 10 levels deep if you wanted.

(configName || DEFAULT_CONFIG_NAME) +
':\n' +
joiValidationErrorsAsTable(error),
})
}
Expand Down
63 changes: 51 additions & 12 deletions test/config.test.js
Expand Up @@ -28,20 +28,50 @@ describe('getConfig', () => {
})
})

it('config file does not exist', async () => {
const context = {
payload: { repository: { default_branch: 'master' } },
config: null,
log: { info: jest.fn(), warn: jest.fn() },
}
const warnSpy = jest.spyOn(context.log, 'warn')

const config = await getConfig({
context,
})

expect(config).toBeNull()
expect(warnSpy).toHaveBeenLastCalledWith(
expect.objectContaining({
stack: expect.stringMatching(/context.config is not a function/),
// In the test, this message is set by Probot. Actually the message below:
// 'Configuration file .github/release-drafter.yml is not found. The configuration file must reside in your default branch.'
}),
expect.stringMatching(/Invalid config file/)
)
})

describe('`replacers` option', () => {
it('validates `replacers` option', async () => {
const context = {
payload: { repository: { default_branch: 'master' } },
config: createGetConfigMock({ replacers: 'bogus' }),
log: { info: jest.fn(), warn: jest.fn() },
}
const warnSpy = jest.spyOn(context.log, 'warn')
const infoSpy = jest.spyOn(context.log, 'info')

const config = await getConfig({
context,
})

expect(
getConfig({
context,
})
).rejects.toThrow(
'child "replacers" fails because ["replacers" must be an array]'
expect(config).toBeNull()
expect(warnSpy).toHaveBeenLastCalledWith(
expect.objectContaining({}),
expect.stringMatching(/Invalid config file/)
)
expect(infoSpy).toHaveBeenLastCalledWith(
expect.stringMatching(/"replacers" must be an array/)
)
})

Expand Down Expand Up @@ -72,13 +102,22 @@ describe('getConfig', () => {
config: createGetConfigMock({ 'sort-direction': 'bogus' }),
log: { info: jest.fn(), warn: jest.fn() },
}
const warnSpy = jest.spyOn(context.log, 'warn')
const infoSpy = jest.spyOn(context.log, 'info')

expect(
getConfig({
context,
})
).rejects.toThrow(
'"sort-direction" must be one of [ascending, descending]'
const config = await getConfig({
context,
})

expect(config).toBeNull()
expect(warnSpy).toHaveBeenLastCalledWith(
expect.objectContaining({}),
expect.stringMatching(/Invalid config file/)
)
expect(infoSpy).toHaveBeenLastCalledWith(
expect.stringMatching(
/"sort-direction" must be one of \[ascending, descending\]/
)
)
})

Expand Down