From 4105a131690db35caea1e8c08c44a00a1a56747e Mon Sep 17 00:00:00 2001 From: Jesse Szwedko Date: Tue, 4 Oct 2022 14:19:07 -0700 Subject: [PATCH 1/4] feat: Allow enum options to be newline delimited only Fixes: #204 Signed-off-by: Jesse Szwedko --- action.yml | 3 +++ src/ConfigParser.js | 7 +++++-- src/ConfigParser.test.js | 12 ++++++++++-- src/parseConfig.js | 13 +++++++++---- 4 files changed, 27 insertions(+), 8 deletions(-) diff --git a/action.yml b/action.yml index ab3323ca4..3baaf6457 100644 --- a/action.yml +++ b/action.yml @@ -44,6 +44,9 @@ inputs: headerPatternCorrespondence: description: "If `headerPattern` is configured, you can use this to define which capturing groups correspond to the type, scope and subject." required: false + requireNewlines: + description: "If `requireNewlines` is `true` then enum configuration (`scopes`, `types`, `disallowScopes`, `ignoreLabels`) will parse the input as newline delimited rather than any whitespace or commas to delimit options." + required: false wip: description: "For work-in-progress PRs you can typically use draft pull requests from Github. However, private repositories on the free plan don't have this option and therefore this action allows you to opt-in to using the special '[WIP]' prefix to indicate this state. This will avoid the validation of the PR title and the pull request checks remain pending. Note that a second check will be reported if this is enabled." required: false diff --git a/src/ConfigParser.js b/src/ConfigParser.js index c307c528a..04df6b3ef 100644 --- a/src/ConfigParser.js +++ b/src/ConfigParser.js @@ -1,9 +1,12 @@ const ENUM_SPLIT_REGEX = /[,\s]\s*/; +const ENUM_SPLIT_NEWLINES_REGEX = /\n/; module.exports = { - parseEnum(input) { + parseEnum(input, onlyNewlines) { + let pattern = onlyNewlines ? ENUM_SPLIT_NEWLINES_REGEX : ENUM_SPLIT_REGEX; + return input - .split(ENUM_SPLIT_REGEX) + .split(pattern) .map((part) => part.trim()) .filter((part) => part.length > 0); }, diff --git a/src/ConfigParser.test.js b/src/ConfigParser.test.js index 0de771861..354acd8b8 100644 --- a/src/ConfigParser.test.js +++ b/src/ConfigParser.test.js @@ -2,7 +2,7 @@ const ConfigParser = require('./ConfigParser'); describe('parseEnum', () => { it('parses commas', () => { - expect(ConfigParser.parseEnum('one, two,three, \nfour ')).toEqual([ + expect(ConfigParser.parseEnum('one, two,three, \nfour ', false)).toEqual([ 'one', 'two', 'three', @@ -11,11 +11,19 @@ describe('parseEnum', () => { }); it('parses white space', () => { - expect(ConfigParser.parseEnum('one two\nthree \n\rfour')).toEqual([ + expect(ConfigParser.parseEnum('one two\nthree \n\rfour', false)).toEqual([ 'one', 'two', 'three', 'four' ]); }); + + it('allows only newlines', () => { + expect(ConfigParser.parseEnum('one two\nthree \n\rfour', true)).toEqual([ + 'one two', + 'three', + 'four' + ]); + }); }); diff --git a/src/parseConfig.js b/src/parseConfig.js index bbfa85aa4..00ca79926 100644 --- a/src/parseConfig.js +++ b/src/parseConfig.js @@ -1,14 +1,19 @@ const ConfigParser = require('./ConfigParser'); module.exports = function parseConfig() { + let requireNewlines; + if (process.env.INPUT_REQUIRENEWLINES) { + newlineScopes = ConfigParser.parseBoolean(process.env.INPUT_REQUIRENEWLINES); + } + let types; if (process.env.INPUT_TYPES) { - types = ConfigParser.parseEnum(process.env.INPUT_TYPES); + types = ConfigParser.parseEnum(process.env.INPUT_TYPES, requireNewlines); } let scopes; if (process.env.INPUT_SCOPES) { - scopes = ConfigParser.parseEnum(process.env.INPUT_SCOPES); + scopes = ConfigParser.parseEnum(process.env.INPUT_SCOPES, requireNewlines); } let requireScope; @@ -18,7 +23,7 @@ module.exports = function parseConfig() { let disallowScopes; if (process.env.INPUT_DISALLOWSCOPES) { - disallowScopes = ConfigParser.parseEnum(process.env.INPUT_DISALLOWSCOPES); + disallowScopes = ConfigParser.parseEnum(process.env.INPUT_DISALLOWSCOPES, requireNewlines); } let subjectPattern; @@ -71,7 +76,7 @@ module.exports = function parseConfig() { let ignoreLabels; if (process.env.INPUT_IGNORELABELS) { - ignoreLabels = ConfigParser.parseEnum(process.env.INPUT_IGNORELABELS); + ignoreLabels = ConfigParser.parseEnum(process.env.INPUT_IGNORELABELS, requireNewlines); } return { From 5fcbcd8d421bdad70a12c4213789b1836c65f966 Mon Sep 17 00:00:00 2001 From: Jesse Szwedko Date: Tue, 4 Oct 2022 15:14:15 -0700 Subject: [PATCH 2/4] Update parseConfig.js --- src/parseConfig.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parseConfig.js b/src/parseConfig.js index 00ca79926..b82852da0 100644 --- a/src/parseConfig.js +++ b/src/parseConfig.js @@ -3,7 +3,7 @@ const ConfigParser = require('./ConfigParser'); module.exports = function parseConfig() { let requireNewlines; if (process.env.INPUT_REQUIRENEWLINES) { - newlineScopes = ConfigParser.parseBoolean(process.env.INPUT_REQUIRENEWLINES); + requireNewlines = ConfigParser.parseBoolean(process.env.INPUT_REQUIRENEWLINES); } let types; From 2710ebc277078f414fc775b474ffed72701d2bdb Mon Sep 17 00:00:00 2001 From: Jesse Szwedko Date: Fri, 7 Oct 2022 16:37:14 -0700 Subject: [PATCH 3/4] Update to only use newlines to delimite enums Signed-off-by: Jesse Szwedko --- README.md | 7 +++++-- action.yml | 11 ++++------- src/ConfigParser.js | 9 +++------ src/ConfigParser.test.js | 21 ++------------------- src/parseConfig.js | 13 ++++--------- 5 files changed, 18 insertions(+), 43 deletions(-) diff --git a/README.md b/README.md index 21fb237c7..084752936 100644 --- a/README.md +++ b/README.md @@ -57,11 +57,13 @@ feat(ui): Add `Button` component. ```yml with: # Configure which types are allowed. + # Newline delimited. # Default: https://github.com/commitizen/conventional-commit-types types: | fix feat # Configure which scopes are allowed. + # Newline delimited. scopes: | core ui @@ -69,6 +71,7 @@ feat(ui): Add `Button` component. requireScope: true # Configure which scopes are disallowed in PR titles. For instance by setting # the value below, `chore(release): ...` and `ci(e2e,release): ...` will be rejected. + # Newline delimited. disallowScopes: | release # Configure additional validation for the subject based on a regex. @@ -84,7 +87,7 @@ feat(ui): Add `Button` component. # If you use GitHub Enterprise, you can set this to the URL of your server githubBaseUrl: https://github.myorg.com/api/v3 # If the PR contains one of these labels, the validation is skipped. - # Multiple labels can be separated by newlines. + # Newline delimited. # If you want to rerun the validation when labels change, you might want # to use the `labeled` and `unlabeled` event triggers in your workflow. ignoreLabels: | @@ -180,4 +183,4 @@ When using "Squash and merge" on a PR with only one commit, GitHub will suggest # Related to `validateSingleCommit` you can opt-in to validate that the PR # title matches a single commit to avoid confusion. validateSingleCommitMatchesPrTitle: true -``` \ No newline at end of file +``` diff --git a/action.yml b/action.yml index 3baaf6457..a1c1340bf 100644 --- a/action.yml +++ b/action.yml @@ -9,16 +9,16 @@ branding: color: 'green' inputs: types: - description: "Provide custom types if you don't want the default ones from https://www.conventionalcommits.org" + description: "Provide custom types if you don't want the default ones from https://www.conventionalcommits.org. Newline delimited." required: false scopes: - description: "Configure which scopes are allowed." + description: "Configure which scopes are allowed. Newline delimited." required: false requireScope: description: "Configure that a scope must always be provided." required: false disallowScopes: - description: 'Configure which scopes are disallowed in PR titles.' + description: 'Configure which scopes are disallowed in PR titles. Newline delimited.' required: false subjectPattern: description: "Configure additional validation for the subject based on a regex. E.g. '^(?![A-Z]).+$' ensures the subject doesn't start with an uppercase character." @@ -36,7 +36,7 @@ inputs: description: "If you use Github Enterprise, you can set this to the URL of your server (e.g. https://github.myorg.com/api/v3)" required: false ignoreLabels: - description: "If the PR contains one of these labels, the validation is skipped. Multiple labels can be separated by newlines. If you want to rerun the validation when labels change, you might want to use the `labeled` and `unlabeled` event triggers in your workflow." + description: "If the PR contains one of these labels, the validation is skipped. Newline delimited. If you want to rerun the validation when labels change, you might want to use the `labeled` and `unlabeled` event triggers in your workflow." required: false headerPattern: description: "If you're using a format for the PR title that differs from the traditional Conventional Commits spec, you can use this to customize the parsing of the type, scope and subject. The `headerPattern` should contain a regex where the capturing groups in parentheses correspond to the parts listed in `headerPatternCorrespondence`. For more details see: https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-commits-parser#headerpattern" @@ -44,9 +44,6 @@ inputs: headerPatternCorrespondence: description: "If `headerPattern` is configured, you can use this to define which capturing groups correspond to the type, scope and subject." required: false - requireNewlines: - description: "If `requireNewlines` is `true` then enum configuration (`scopes`, `types`, `disallowScopes`, `ignoreLabels`) will parse the input as newline delimited rather than any whitespace or commas to delimit options." - required: false wip: description: "For work-in-progress PRs you can typically use draft pull requests from Github. However, private repositories on the free plan don't have this option and therefore this action allows you to opt-in to using the special '[WIP]' prefix to indicate this state. This will avoid the validation of the PR title and the pull request checks remain pending. Note that a second check will be reported if this is enabled." required: false diff --git a/src/ConfigParser.js b/src/ConfigParser.js index 04df6b3ef..b0f9c63e0 100644 --- a/src/ConfigParser.js +++ b/src/ConfigParser.js @@ -1,12 +1,9 @@ -const ENUM_SPLIT_REGEX = /[,\s]\s*/; -const ENUM_SPLIT_NEWLINES_REGEX = /\n/; +const ENUM_SPLIT_REGEX = /\n/; module.exports = { - parseEnum(input, onlyNewlines) { - let pattern = onlyNewlines ? ENUM_SPLIT_NEWLINES_REGEX : ENUM_SPLIT_REGEX; - + parseEnum(input) { return input - .split(pattern) + .split(ENUM_SPLIT_REGEX) .map((part) => part.trim()) .filter((part) => part.length > 0); }, diff --git a/src/ConfigParser.test.js b/src/ConfigParser.test.js index 354acd8b8..3b99d5700 100644 --- a/src/ConfigParser.test.js +++ b/src/ConfigParser.test.js @@ -1,29 +1,12 @@ const ConfigParser = require('./ConfigParser'); describe('parseEnum', () => { - it('parses commas', () => { - expect(ConfigParser.parseEnum('one, two,three, \nfour ', false)).toEqual([ + it('parses newline-delimited lists, trimming whitespace', () => { + expect(ConfigParser.parseEnum('one \ntwo \nthree \n\rfour')).toEqual([ 'one', 'two', 'three', 'four' ]); }); - - it('parses white space', () => { - expect(ConfigParser.parseEnum('one two\nthree \n\rfour', false)).toEqual([ - 'one', - 'two', - 'three', - 'four' - ]); - }); - - it('allows only newlines', () => { - expect(ConfigParser.parseEnum('one two\nthree \n\rfour', true)).toEqual([ - 'one two', - 'three', - 'four' - ]); - }); }); diff --git a/src/parseConfig.js b/src/parseConfig.js index b82852da0..bbfa85aa4 100644 --- a/src/parseConfig.js +++ b/src/parseConfig.js @@ -1,19 +1,14 @@ const ConfigParser = require('./ConfigParser'); module.exports = function parseConfig() { - let requireNewlines; - if (process.env.INPUT_REQUIRENEWLINES) { - requireNewlines = ConfigParser.parseBoolean(process.env.INPUT_REQUIRENEWLINES); - } - let types; if (process.env.INPUT_TYPES) { - types = ConfigParser.parseEnum(process.env.INPUT_TYPES, requireNewlines); + types = ConfigParser.parseEnum(process.env.INPUT_TYPES); } let scopes; if (process.env.INPUT_SCOPES) { - scopes = ConfigParser.parseEnum(process.env.INPUT_SCOPES, requireNewlines); + scopes = ConfigParser.parseEnum(process.env.INPUT_SCOPES); } let requireScope; @@ -23,7 +18,7 @@ module.exports = function parseConfig() { let disallowScopes; if (process.env.INPUT_DISALLOWSCOPES) { - disallowScopes = ConfigParser.parseEnum(process.env.INPUT_DISALLOWSCOPES, requireNewlines); + disallowScopes = ConfigParser.parseEnum(process.env.INPUT_DISALLOWSCOPES); } let subjectPattern; @@ -76,7 +71,7 @@ module.exports = function parseConfig() { let ignoreLabels; if (process.env.INPUT_IGNORELABELS) { - ignoreLabels = ConfigParser.parseEnum(process.env.INPUT_IGNORELABELS, requireNewlines); + ignoreLabels = ConfigParser.parseEnum(process.env.INPUT_IGNORELABELS); } return { From 46a5661e3e23fd4627ff90403b9499ffd3ba5c21 Mon Sep 17 00:00:00 2001 From: Jesse Szwedko Date: Tue, 11 Oct 2022 06:52:55 -0700 Subject: [PATCH 4/4] PR feedback Signed-off-by: Jesse Szwedko --- README.md | 16 +++++++--------- action.yml | 8 ++++---- src/ConfigParser.test.js | 2 +- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 084752936..e0f9d40d2 100644 --- a/README.md +++ b/README.md @@ -56,22 +56,20 @@ feat(ui): Add `Button` component. ```yml with: - # Configure which types are allowed. - # Newline delimited. + # Configure which types are allowed (newline delimited). # Default: https://github.com/commitizen/conventional-commit-types types: | fix feat - # Configure which scopes are allowed. - # Newline delimited. + # Configure which scopes are allowed (newline delimited). scopes: | core ui # Configure that a scope must always be provided. requireScope: true - # Configure which scopes are disallowed in PR titles. For instance by setting - # the value below, `chore(release): ...` and `ci(e2e,release): ...` will be rejected. - # Newline delimited. + # Configure which scopes (newline delimited) are disallowed in PR + # titles. For instance by setting # the value below, `chore(release): + # ...` and `ci(e2e,release): ...` will be rejected. disallowScopes: | release # Configure additional validation for the subject based on a regex. @@ -86,8 +84,8 @@ feat(ui): Add `Button` component. doesn't start with an uppercase character. # If you use GitHub Enterprise, you can set this to the URL of your server githubBaseUrl: https://github.myorg.com/api/v3 - # If the PR contains one of these labels, the validation is skipped. - # Newline delimited. + # If the PR contains one of these labels (newline delimited), the + # validation is skipped. # If you want to rerun the validation when labels change, you might want # to use the `labeled` and `unlabeled` event triggers in your workflow. ignoreLabels: | diff --git a/action.yml b/action.yml index a1c1340bf..9a51aa103 100644 --- a/action.yml +++ b/action.yml @@ -9,16 +9,16 @@ branding: color: 'green' inputs: types: - description: "Provide custom types if you don't want the default ones from https://www.conventionalcommits.org. Newline delimited." + description: "Provide custom types (newline delimited) if you don't want the default ones from https://www.conventionalcommits.org." required: false scopes: - description: "Configure which scopes are allowed. Newline delimited." + description: "Configure which scopes are allowed (newline delimited)." required: false requireScope: description: "Configure that a scope must always be provided." required: false disallowScopes: - description: 'Configure which scopes are disallowed in PR titles. Newline delimited.' + description: 'Configure which scopes are disallowed in PR titles (newline delimited).' required: false subjectPattern: description: "Configure additional validation for the subject based on a regex. E.g. '^(?![A-Z]).+$' ensures the subject doesn't start with an uppercase character." @@ -36,7 +36,7 @@ inputs: description: "If you use Github Enterprise, you can set this to the URL of your server (e.g. https://github.myorg.com/api/v3)" required: false ignoreLabels: - description: "If the PR contains one of these labels, the validation is skipped. Newline delimited. If you want to rerun the validation when labels change, you might want to use the `labeled` and `unlabeled` event triggers in your workflow." + description: "If the PR contains one of these labels (newline delimited), the validation is skipped. If you want to rerun the validation when labels change, you might want to use the `labeled` and `unlabeled` event triggers in your workflow." required: false headerPattern: description: "If you're using a format for the PR title that differs from the traditional Conventional Commits spec, you can use this to customize the parsing of the type, scope and subject. The `headerPattern` should contain a regex where the capturing groups in parentheses correspond to the parts listed in `headerPatternCorrespondence`. For more details see: https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-commits-parser#headerpattern" diff --git a/src/ConfigParser.test.js b/src/ConfigParser.test.js index 3b99d5700..8eb28cc67 100644 --- a/src/ConfigParser.test.js +++ b/src/ConfigParser.test.js @@ -2,7 +2,7 @@ const ConfigParser = require('./ConfigParser'); describe('parseEnum', () => { it('parses newline-delimited lists, trimming whitespace', () => { - expect(ConfigParser.parseEnum('one \ntwo \nthree \n\rfour')).toEqual([ + expect(ConfigParser.parseEnum('one \ntwo \nthree \r\nfour')).toEqual([ 'one', 'two', 'three',