Skip to content

Commit

Permalink
fix: unknown types should not be accepted by default
Browse files Browse the repository at this point in the history
Originally, the validation on Conventional Commit types was only
working correctly in case the user would provide a list of
additional types.

This would result in the following commit to be accepted:
```
feet: feed it
```

Worst case, this would lead to an absence of a SemVer bump
in case automation relies on the types.
  • Loading branch information
Kevin-de-Jong committed Dec 12, 2023
1 parent 2845c7f commit 18e4ea7
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 29 deletions.
42 changes: 23 additions & 19 deletions src/requirements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ function createError(
? [commit.commit.subject, "", ...commit.commit.body.split("\n")]
: [commit.commit.subject]
)
.addFixitHint(FixItHint.create({ index: data.index, length: data.value?.length || 1 }));
.addFixitHint(FixItHint.create({ index: data.index, length: data.value?.length ?? 1 }));
}

/**
Expand Down Expand Up @@ -168,50 +168,54 @@ class CC05 implements ICommitRequirement {
}

/**
* A scope MAY be provided after a type. A scope MUST consist of one of the configured values (feat, fix, ...) surrounded by parenthesis
* A scope MAY be provided after a type. A scope MUST consist of one of the configured values (...) surrounded by parenthesis
*/
class EC01 implements ICommitRequirement {
id = "EC-01";
description =
"A scope MAY be provided after a type. A scope MUST consist of one of the configured values (feat, fix, ...) surrounded by parenthesis";
"A scope MAY be provided after a type. A scope MUST consist of one of the configured values (...) surrounded by parenthesis";

validate(commit: IRawConventionalCommit, options?: IConventionalCommitOptions): DiagnosticsMessage[] {
this.description = `A scope MAY be provided after a type. A scope MUST consist of one of the configured values (${options?.scopes?.join(
", "
)}) surrounded by parenthesis`;
const uniqueScopeList = Array.from(new Set<string>(options?.scopes ?? []));
if (uniqueScopeList.length === 0) return [];

if (options === undefined || options.scopes === undefined || options.scopes.length === 0) return [];
if (commit.scope.value === undefined || options.scopes.includes(commit.scope.value.replace(/[()]+/g, "")))
if (commit.scope.value === undefined || uniqueScopeList.includes(commit.scope.value.replace(/[()]+/g, "")))
return [];

this.description = `A scope MAY be provided after a type. A scope MUST consist of one of the configured values (${uniqueScopeList.join(
", "
)}) surrounded by parenthesis`;

return [
createError(commit, this.description, ["A scope MUST consist of", `(${options?.scopes?.join(", ")})`], "scope"),
createError(commit, this.description, ["A scope MUST consist of", `(${uniqueScopeList.join(", ")})`], "scope"),
];
}
}

/**
* Commits MUST be prefixed with a type, which consists of one of the configured values (...)
* Commits MUST be prefixed with a type, which consists of one of the configured values (feat, fix, ...)
*/
class EC02 implements ICommitRequirement {
id = "EC-02";
description = "Commits MUST be prefixed with a type, which consists of one of the configured values (...)";
description = "Commits MUST be prefixed with a type, which consists of one of the configured values (feat, fix, ...)";

validate(commit: IRawConventionalCommit, options?: IConventionalCommitOptions): DiagnosticsMessage[] {
this.description = `Commits MUST be prefixed with a type, which consists of one of the configured values (${[
"feat",
"fix",
...(options?.types ?? []),
].join(", ")}).`;
const uniqueAddedTypes = new Set<string>(options?.types ?? []);
if (uniqueAddedTypes.has("feat")) uniqueAddedTypes.delete("feat");
if (uniqueAddedTypes.has("fix")) uniqueAddedTypes.delete("fix");
const expectedTypes = ["feat", "fix", ...Array.from(uniqueAddedTypes)];

this.description = `Commits MUST be prefixed with a type, which consists of one of the configured values (${expectedTypes.join(
", "
)}).`;

if (options === undefined || options.types === undefined || options.types.length === 0) return [];
if (commit.type.value !== undefined && ["feat", "fix", ...options.types].includes(commit.type.value)) return [];
if (commit.type.value !== undefined && expectedTypes.includes(commit.type.value)) return [];

return [
createError(
commit,
this.description,
["prefixed with a type, which consists of", `(${["feat", "fix", ...(options?.types ?? [])].join(", ")})`],
["prefixed with a type, which consists of", `(${expectedTypes.join(", ")})`],
"type"
),
];
Expand Down
14 changes: 4 additions & 10 deletions test/conventional_commit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const validateRequirement = (message: string, expected: string, options?: IConve
if (!found) {
throw new Error(
`Expected error message '${expected}' not found in: ${removeColors(
error.errors.map(e => e.message).join("\n")
error.errors.map(e => e.message.text).join("\n")
)}`
);
} else {
Expand All @@ -51,13 +51,6 @@ describe("Conventional Commits specification", () => {
"feat: add new feature",
"fix: fix bug",
"fix!: fix bug with breaking change",
"docs: update documentation",
"style: update style",
"style(format): update style with scope",
"refactor: refactor code",
"test: update tests",
"test(unit)!: update unit tests which leads to a breaking change",
"chore: update build scripts",
"feat(login): add support google oauth (#12)",
]) {
expect(() => {
Expand Down Expand Up @@ -162,7 +155,7 @@ describe("Extended Conventional Commits specification", () => {
message,
"A scope MAY be provided after a type. A scope MUST consist of one of the configured values (action, cli) surrounded by parenthesis",
{
scopes: ["action", "cli"],
scopes: ["action", "action", "cli", "cli"],
}
);
}
Expand All @@ -174,7 +167,8 @@ describe("Extended Conventional Commits specification", () => {
message,
"Commits MUST be prefixed with a type, which consists of one of the configured values (feat, fix, build, perf)",
{
types: ["build", "perf"],
scopes: ["scope"],
types: ["feat", "build", "build", "perf", "perf", "fix"],
}
);
}
Expand Down

0 comments on commit 18e4ea7

Please sign in to comment.