Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .github/scripts/validate-structure.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,34 @@ function validateFilePath(filePath) {
const normalized = filePath.replace(/\\/g, '/');
const segments = normalized.split('/');

// Check for invalid characters that break local file systems
for (let i = 0; i < segments.length; i++) {
const segment = segments[i];

// Check for trailing periods (invalid on Windows)
if (segment.endsWith('.')) {
return `Invalid folder/file name '${segment}' in path '${normalized}': Names cannot end with a period (.) as this breaks local file system sync on Windows.`;
}

// Check for trailing spaces (invalid on Windows)
if (segment.endsWith(' ')) {
return `Invalid folder/file name '${segment}' in path '${normalized}': Names cannot end with a space as this breaks local file system sync on Windows.`;
}

// Check for reserved Windows names
const reservedNames = ['CON', 'PRN', 'AUX', 'NUL', 'COM1', 'COM2', 'COM3', 'COM4', 'COM5', 'COM6', 'COM7', 'COM8', 'COM9', 'LPT1', 'LPT2', 'LPT3', 'LPT4', 'LPT5', 'LPT6', 'LPT7', 'LPT8', 'LPT9'];
const nameWithoutExt = segment.split('.')[0].toUpperCase();
if (reservedNames.includes(nameWithoutExt)) {
return `Invalid folder/file name '${segment}' in path '${normalized}': '${nameWithoutExt}' is a reserved name on Windows and will break local file system sync.`;
}

// Check for invalid characters (Windows and general file system restrictions)
const invalidChars = /[<>:"|?*\x00-\x1F]/;
if (invalidChars.test(segment)) {
return `Invalid folder/file name '${segment}' in path '${normalized}': Contains characters that are invalid on Windows file systems (< > : " | ? * or control characters).`;
}
}

if (!allowedCategories.has(segments[0])) {
return null;
}
Expand Down
30 changes: 29 additions & 1 deletion .github/workflows/validate-structure.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ jobs:
cat "$tmp_error" >&2
if grep -q 'Folder structure violations found' "$tmp_output" "$tmp_error"; then
# Save validation output for use in PR comment
cat "$tmp_output" "$tmp_error" > "$RUNNER_TEMP/validation_output.txt"
echo "status=failed" >> "$GITHUB_OUTPUT"
exit 0
fi
Expand All @@ -87,11 +89,37 @@ jobs:
const owner = context.repo.owner;
const repo = context.repo.repo;
const fs = require('fs');
const output = fs.readFileSync(process.env.RUNNER_TEMP + '/validation_output.txt', 'utf8');
let commentBody = `Thank you for your contribution. However, it doesn't comply with our contributing guidelines.\n\n`;
// Check if the error is about invalid file/folder names
if (output.includes('Names cannot end with a period') ||
output.includes('Names cannot end with a space') ||
output.includes('is a reserved name on Windows') ||
output.includes('Contains characters that are invalid')) {
commentBody += `**❌ Invalid File/Folder Names Detected**\n\n`;
commentBody += `Your contribution contains file or folder names that will break when syncing to local file systems (especially Windows):\n\n`;
commentBody += `\`\`\`\n${output}\n\`\`\`\n\n`;
commentBody += `**Common issues:**\n`;
commentBody += `- Folder/file names ending with a period (.) - not allowed on Windows\n`;
commentBody += `- Folder/file names ending with spaces - not allowed on Windows\n`;
commentBody += `- Reserved names like CON, PRN, AUX, NUL, COM1-9, LPT1-9 - not allowed on Windows\n`;
commentBody += `- Invalid characters: < > : " | ? * or control characters\n\n`;
commentBody += `Please rename these files/folders to be compatible with all operating systems.\n\n`;
} else {
commentBody += `As a reminder, the general requirements (as outlined in the [CONTRIBUTING.md file](https://github.com/ServiceNowDevProgram/code-snippets/blob/main/CONTRIBUTING.md)) are the following: follow the folder+subfolder guidelines and include a README.md file explaining what the code snippet does.\n\n`;
commentBody += `**Validation errors:**\n\`\`\`\n${output}\n\`\`\`\n\n`;
}
commentBody += `Review your contribution against the guidelines and make the necessary adjustments. Closing this for now. Once you make additional changes, feel free to re-open this Pull Request or create a new one.`;
await github.rest.issues.createComment({
owner,
repo,
issue_number: pullNumber,
body: `Thank you for your contribution. However, it doesn't comply with our contributing guidelines. As a reminder, the general requirements (as outlined in the [CONTRIBUTING.md file](https://github.com/ServiceNowDevProgram/code-snippets/blob/main/CONTRIBUTING.md)) are the following: follow the folder+subfolder guidelines and include a README.md file explaining what the code snippet does. Review your contribution against the guidelines and make the necessary adjustments. Closing this for now. Once you make additional changes, feel free to re-open this Pull Request or create a new one.`.trim()
body: commentBody.trim()
});
await github.rest.pulls.update({
Expand Down
Loading