[rn-changelog-generator] Add validation command and export (#2260)

Co-authored-by: Luna Wei <luwe@fb.com>
This commit is contained in:
Luna 2023-03-06 10:18:05 +00:00 коммит произвёл GitHub
Родитель d348a78c58
Коммит 3fa093e89d
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
7 изменённых файлов: 163 добавлений и 1 удалений

Просмотреть файл

@ -0,0 +1,5 @@
---
"@rnx-kit/rn-changelog-generator": minor
---
Adding validation command to verify if a commit follows a React Native changelog

Просмотреть файл

@ -26,7 +26,7 @@
"bundle": "rnx-kit-scripts bundle",
"format": "rnx-kit-scripts format",
"lint": "rnx-kit-scripts lint",
"test:local": "rnx-kit-scripts test"
"test:local": "RN_REPO='../../../react-native' rnx-kit-scripts test"
},
"devDependencies": {
"@rnx-kit/scripts": "*",
@ -35,6 +35,7 @@
"deepmerge": "^4.2.2",
"eslint": "^8.0.0",
"fast-levenshtein": "^3.0.0",
"jest": "^27.0.0",
"p-limit": "^3.1.0",
"prettier": "^2.8.0",
"typescript": "^4.0.0",

Просмотреть файл

@ -1,5 +1,7 @@
import generator from "./generator";
import single from "./single";
import validate from "./validate";
import validateChangelog from "./utils/validateChangelog";
if (require.main === module) {
require("yargs")
@ -15,5 +17,15 @@ if (require.main === module) {
single.args,
single.handler
)
.command(
"validate",
"Validate if a commit message meets changelog requirements. Returns 'missing', 'valid' or 'invalid'",
validate.args,
validate.handler
)
.help("help").argv;
}
export default {
validate: validateChangelog,
};

Просмотреть файл

@ -0,0 +1,19 @@
// Regex looks for given categories, types, a file/framework/component, and a message - broken into 4 capture groups
const changelogRegex =
/\[\s?(ANDROID|GENERAL|IOS|INTERNAL)\s?\]\s?\[\s?(BREAKING|ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY)\s?\]\s*?-?\s*?(.*)/i;
const internalChangelogRegex = /\[\s?(INTERNAL)\s?\].*/gi;
export default function validateChangelog(commitMsg: string) {
if (!commitMsg.toLowerCase().includes("changelog:")) {
return "missing";
}
const hasValidChangelog = changelogRegex.test(commitMsg);
const hasValidInternalChangelog = internalChangelogRegex.test(commitMsg);
if (hasValidChangelog || hasValidInternalChangelog) {
return "valid";
}
return "invalid";
}

Просмотреть файл

@ -0,0 +1,18 @@
import validate from "./utils/validateChangelog";
function handler(argv: { commitMsg: string }) {
return validate(argv.commitMsg);
}
export default {
handler,
args: {
commitMsg: {
alias: "c",
string: true,
describe:
"Validate if commit message follows changelog format. Returns 'missing', 'invalid', or 'valid'.",
demandOption: true,
},
},
};

Просмотреть файл

@ -0,0 +1,106 @@
import validateChangelog from "../../src/utils/validateChangelog";
const missing = `
This is a changelog that is missing the formatted changelog.
`;
const invalidWhenOnlyPlatformAndNotInternal = `
Changelog: [Android]
`;
const invalidWhenFirstCategoryIsntValid = `
Changelog: [Invalid Platform][Breaking]
`;
const invalidWhenSecondCategoryIsntValid = `
Changelog: [General][Invalid Type]
`;
const invalidWhenInternalAndInvalidSecondaryCategory = `
CHANGELOG: [iOS][Invalid]
`;
const missingWhenChangelogMissingColon = `
CHANGELOG [iOS][Breaking]
`;
const validWhenFormattingAround = `
Some message stuff about this
----
## CHANGELOG: [General][Breaking]
`;
const validdWhenMoreThan2 = `
Changelog: [iOS][Changed][Removed]
`;
const validChangelog = `
Changelog: [iOS][Changed][Removed]
`;
const validWhenOnlyInternal = `
Changelog: [Internal]
`;
const invalidSecondCategory = `
Changelog: [Internal][Android] - Blah blah
fejafkeaj jkf
`;
describe(validateChangelog, () => {
describe("missing changelog", () => {
it("should identify if missing changelog", () => {
expect(validateChangelog(missing)).toBe("missing");
});
it("when missing colon after Changelog", () => {
expect(validateChangelog(missingWhenChangelogMissingColon)).toBe(
"missing"
);
});
});
describe("should identify invalid changelog", () => {
it("when only platform and its not internal", () => {
expect(validateChangelog(invalidWhenOnlyPlatformAndNotInternal)).toBe(
"invalid"
);
});
it("when first category isnt valid", () => {
expect(validateChangelog(invalidWhenFirstCategoryIsntValid)).toBe(
"invalid"
);
});
it("when second category isnt valid", () => {
expect(validateChangelog(invalidWhenSecondCategoryIsntValid)).toBe(
"invalid"
);
});
it("when internal but invalid secondary category", () => {
expect(
validateChangelog(invalidWhenInternalAndInvalidSecondaryCategory)
).toBe("invalid");
});
});
describe("should identify changelog as valid", () => {
it("when second category is invalid but ignored", () => {
expect(validateChangelog(invalidSecondCategory)).toBe("valid");
});
it("when there is formatting around changelog", () => {
expect(validateChangelog(validWhenFormattingAround)).toBe("valid");
});
it("when only internal", () => {
expect(validateChangelog(validWhenOnlyInternal)).toBe("valid");
});
it("when valid changelog", () => {
expect(validateChangelog(validChangelog)).toBe("valid");
});
it("when more than two categories provided", () => {
expect(validateChangelog(validdWhenMoreThan2)).toBe("valid");
});
});
});

Просмотреть файл

@ -3569,6 +3569,7 @@ __metadata:
deepmerge: ^4.2.2
eslint: ^8.0.0
fast-levenshtein: ^3.0.0
jest: ^27.0.0
p-limit: ^3.1.0
prettier: ^2.8.0
typescript: ^4.0.0