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

XS⚠️ ◾ Validating all frontmatter for issues #7465

Merged
merged 67 commits into from
Dec 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
6402fc0
add-all-frontmatter-validator
JackDevAU Dec 6, 2023
0e0d2be
testing - add to on PR
JackDevAU Dec 6, 2023
58f931a
update
JackDevAU Dec 6, 2023
af5f9e4
another attempt
JackDevAU Dec 6, 2023
a1c1f13
test
JackDevAU Dec 6, 2023
e667f97
update script to allow multiple errors
JackDevAU Dec 7, 2023
ebe7482
x
JackDevAU Dec 7, 2023
b33c615
allow file as input
JackDevAU Dec 7, 2023
2085085
x
JackDevAU Dec 7, 2023
c5b6591
x
JackDevAU Dec 7, 2023
a27bd39
x
JackDevAU Dec 7, 2023
da88d8f
x
JackDevAU Dec 7, 2023
c1ce30d
Merge branch 'add-frontmatter-all-action' of https://github.com/SSWCo…
JackDevAU Dec 7, 2023
78a7c4e
x
JackDevAU Dec 7, 2023
c82214b
x
JackDevAU Dec 7, 2023
1f81c24
x
JackDevAU Dec 7, 2023
c2c35fd
x
JackDevAU Dec 7, 2023
e2d9ac2
x
JackDevAU Dec 7, 2023
9ab6a2e
x
JackDevAU Dec 7, 2023
0b3812a
x
JackDevAU Dec 7, 2023
30f7147
x
JackDevAU Dec 7, 2023
babc2d4
x
JackDevAU Dec 7, 2023
5d66f49
x
JackDevAU Dec 7, 2023
0c8a55b
x
JackDevAU Dec 7, 2023
8a2f70c
x
JackDevAU Dec 7, 2023
f1db8c4
x
JackDevAU Dec 7, 2023
c8ce77d
x
JackDevAU Dec 7, 2023
2da095a
x
JackDevAU Dec 7, 2023
a4bf177
x
JackDevAU Dec 7, 2023
88cc1ee
x
JackDevAU Dec 7, 2023
7db5462
x
JackDevAU Dec 7, 2023
78d57e3
x
JackDevAU Dec 7, 2023
139821e
x
JackDevAU Dec 7, 2023
b30955e
x
JackDevAU Dec 7, 2023
a508438
x
JackDevAU Dec 7, 2023
ab67e32
x
JackDevAU Dec 7, 2023
14174e0
x
JackDevAU Dec 7, 2023
45d13ee
x
JackDevAU Dec 7, 2023
09b3e70
x
JackDevAU Dec 7, 2023
05a250f
x
JackDevAU Dec 7, 2023
6f3b6a0
x
JackDevAU Dec 7, 2023
b5f878e
x
JackDevAU Dec 7, 2023
a8a9cd3
x
JackDevAU Dec 7, 2023
013b4db
x
JackDevAU Dec 7, 2023
d06485d
x
JackDevAU Dec 7, 2023
23f2b77
x
JackDevAU Dec 7, 2023
6dc7021
x
JackDevAU Dec 7, 2023
494564d
x
JackDevAU Dec 7, 2023
79d9635
x
JackDevAU Dec 7, 2023
e295f45
x
JackDevAU Dec 7, 2023
4727375
x
JackDevAU Dec 7, 2023
7ff321f
x
JackDevAU Dec 7, 2023
e206cf0
x
JackDevAU Dec 7, 2023
a1f3cdc
x
JackDevAU Dec 7, 2023
6aac6d9
x
JackDevAU Dec 7, 2023
4e30123
x
JackDevAU Dec 7, 2023
53edb2b
x
JackDevAU Dec 7, 2023
6b25397
x
JackDevAU Dec 7, 2023
1106019
x
JackDevAU Dec 7, 2023
7c9c1a9
x
JackDevAU Dec 7, 2023
936593d
x
JackDevAU Dec 7, 2023
e564c26
x
JackDevAU Dec 7, 2023
77d2d78
x
JackDevAU Dec 7, 2023
5919154
x
JackDevAU Dec 7, 2023
19d5111
x
JackDevAU Dec 7, 2023
b24e926
x
JackDevAU Dec 7, 2023
d9aeb6e
x
JackDevAU Dec 7, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions .github/workflows/validate-frontmatter-all.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Validate-Frontmatter-in-All-Rules

on:
push:
branches: [main]
workflow_dispatch:

jobs:
validate-all-frontmatter:
runs-on: ubuntu-latest
permissions:
contents: read

steps:
- name: Check out repository
uses: actions/checkout@v3
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}

- name: Set up Node.js
uses: actions/setup-node@v3

- name: Find all Markdown files in rules
run: |
find rules -type f -name '*.md' > all_rules_files.txt
echo "Found Markdown files:"
cat all_rules_files.txt

- name: Install dependencies
run: |
cd scripts/frontmatter-validator
npm install

- name: Validate Frontmatter in Rule Files
id: validate_frontmatter
run: |
node scripts/frontmatter-validator/frontmatter-validator.js --file all_rules_files.txt > validation_results.txt

- name: Create Job Summary
if: always()
run: |
echo "## Frontmatter Validation Issues" >> $GITHUB_STEP_SUMMARY
if [ -s validation_results.txt ]; then
cat validation_results.txt >> $GITHUB_STEP_SUMMARY
else
echo "No validation issues detected." >> $GITHUB_STEP_SUMMARY
fi

137 changes: 89 additions & 48 deletions scripts/frontmatter-validator/frontmatter-validator.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
const fs = require('fs');
const ajv = require('ajv');
const yaml = require('js-yaml');
const addFormats = require('ajv-formats');
const ajvErrors = require('ajv-errors');
const fs = require("fs");
const ajv = require("ajv");
const yaml = require("js-yaml");
const addFormats = require("ajv-formats");
const ajvErrors = require("ajv-errors");

let allErrors = [];

const schemas = {
rule: loadSchema('./schema/rule-schema.json'),
category: loadSchema('./schema/category-schema.json'),
top_category: loadSchema('./schema/top-category-schema.json'),
}
rule: loadSchema("schema/rule-schema.json"),
category: loadSchema("schema/category-schema.json"),
top_category: loadSchema("schema/top-category-schema.json"),
};

const validator = initializeValidator();

Expand All @@ -25,53 +27,60 @@ function initializeValidator() {
}

function loadSchema(schemaPath) {
return JSON.parse(fs.readFileSync(schemaPath, 'utf8'));
const args = process.argv.slice(2);
let fullPath = `scripts/frontmatter-validator/${schemaPath}`;
fullPath = args.includes("--file")
? `scripts/frontmatter-validator/${schemaPath}`
: schemaPath;

// todo fix for non file input
const json = JSON.parse(fs.readFileSync(fullPath, "utf8"));
return json;
}

function matchSchema(filePath) {
if (filePath.endsWith('rule.md')) {
return validator.getSchema('rule');
} else if (filePath.indexOf('/categories') !== -1 && !filePath.endsWith('index.md')) {
return validator.getSchema('category');
} else if (filePath.indexOf('/categories') !== -1 && filePath.endsWith('index.md')) {
return validator.getSchema('top_category');
if (filePath.endsWith("rule.md")) {
return validator.getSchema("rule");
} else if (
filePath.indexOf("/categories") !== -1 &&
!filePath.endsWith("index.md")
) {
return validator.getSchema("category");
} else if (
filePath.indexOf("/categories") !== -1 &&
filePath.endsWith("index.md")
) {
return validator.getSchema("top_category");
}
}

function validateFrontmatter(filePath) {
if (filePath.indexOf('.github') !== -1) {
return
}

if (!fs.existsSync(filePath)) {
console.error(`File ${filePath} does not exist.`);
return
if (!fs.existsSync(filePath) || filePath.indexOf(".github") !== -1) {
return; // Skip if file does not exist or is in .github directory
}

const fileContents = fs.readFileSync(filePath, 'utf8');
const fileContents = fs.readFileSync(filePath, "utf8");
const frontmatter = parseFrontmatter(filePath, fileContents);

const validate = matchSchema(filePath);
const isValid = validate(frontmatter);

if (!isValid && validate.errors) {
const errorList = validate.errors.filter(error => {
return error.keyword === 'errorMessage' || error.keyword === 'required'
})

if (errorList.length >= 1) {
console.log(`Invalid Frontmatter detected in ${filePath.replaceAll('../', '')}, please fix the following issues:`);
errorList.forEach((error, index) => {
console.log(`${index + 1}. ${error.message}`);
})
process.exit(1);
let fileErrors = validate.errors
.filter(
(error) =>
error.keyword === "errorMessage" || error.keyword === "required"
)
.map((error) => error.message);

if (fileErrors.length > 0) {
allErrors.push({ filePath, fileErrors });
}
}
}

function parseFrontmatter(filePath, fileContents) {
if (!fileContents) return {}
if (!fileContents) return {};

try {
const frontmatterMatch = /^---([\s\S]*?)---/.exec(fileContents);
const frontmatterString = frontmatterMatch[1];
Expand All @@ -80,26 +89,58 @@ function parseFrontmatter(filePath, fileContents) {
});
return frontmatter;
} catch (error) {
console.log(`Invalid Frontmatter detected in ${filePath.replaceAll('../', '')}: missing '---'`);
process.exit(1);
allErrors.push({
filePath,
fileErrors: ["missing '---'"],
});
}
}

function main() {
const eventType = process.env.GITHUB_EVENT_NAME;
function validateFiles(fileListPath) {
const fileContents = fs.readFileSync(fileListPath, "utf8");
const filePaths = fileContents.trim().split("\n");

if (eventType === 'pull_request') {
const filesChanged = process.argv[2];
filePaths.forEach((file) => {
if (file.endsWith(".md")) {
validateFrontmatter(file);
}
});
}

function main() {
const args = process.argv.slice(2);

if (args.includes("--file")) {
const fileListIndex = args.indexOf("--file") + 1;
const fileListPath = args[fileListIndex];
validateFiles(fileListPath);
} else {
const filesChanged = args[0];
if (filesChanged) {
const folders = filesChanged
.split(',')
.filter((file) => file.endsWith('.md'))
const filePaths = filesChanged
.split(",")
.filter((file) => file.endsWith(".md"))
.map((file) => `../../${file}`);

folders.forEach((file) => validateFrontmatter(file));
filePaths.forEach(validateFrontmatter);
}
}

if (allErrors.length === 0) {
console.log("No frontmatter validation errors found.");
return;
}


allErrors.forEach(({ filePath, fileErrors }) => {
console.log(`## Rule: [${filePath}](https://github.com/SSWConsulting/SSW.Rules.Content/tree/main/${filePath})\n`);
console.log("Issues:");
fileErrors.forEach((issue) => console.log(`- **${issue}**`));
console.log("\n");
console.log("\n");
});
process.exit(1);

process.exit(1);
}

main();
Loading