Skip to content

Commit 4e54cc4

Browse files
Merge pull request joshjohanning#63 from joshjohanning/lint-scripts-readme
feat: lint ./scripts/README.md
2 parents 9a36533 + ecaaad6 commit 4e54cc4

File tree

4 files changed

+57
-19
lines changed

4 files changed

+57
-19
lines changed
Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
1-
// Call manually via: node ./.github/scripts/lint-gh-cli-readme.js
1+
// Call manually via: node ./.github/scripts/lint-readme.js
2+
// Defaults to the `./gh-cli` directory
3+
// Check `./scripts` directory by calling: node ./.github/scripts/lint-readme.js ./scripts '##' '# scripts'
4+
25
// note this is only looking in files committed / staged, not all files in the directory
36

47
const fs = require('fs');
58
const path = require('path');
69
const { execSync } = require('child_process');
710

8-
const directoryPath = './gh-cli';
11+
const directoryPath = process.argv[2] || './gh-cli';
12+
const headingLevel = process.argv[3] || '###';
13+
const parentHeading = process.argv[4] || '## Scripts';
14+
915
const readmePath = path.join(directoryPath, 'README.md');
1016

1117
// Read README.md content
@@ -18,29 +24,49 @@ const gitFiles = execSync('git ls-files', { cwd: directoryPath, encoding: 'utf-8
1824
const files = gitFiles.split('\n');
1925

2026
// Filter out .sh files in the root directory (excluding those in subdirectories)
21-
const shFiles = files.filter(file => file.endsWith('.sh') && !file.includes('/'));
27+
const fileExtensions = ['.sh', '.ps1', '.js', '.mjs', '.py'];
28+
29+
const filteredFiles = files.filter(file => {
30+
return fileExtensions.some(extension => file.endsWith(extension)) && !file.includes('/');
31+
});
32+
33+
const subdirectories = files.reduce((acc, file) => {
34+
if (file.includes('/')) {
35+
const subdirectory = file.split('/')[0];
36+
if (subdirectory !== 'internal' && !acc.includes(subdirectory)) {
37+
acc.push(subdirectory);
38+
}
39+
}
40+
return acc;
41+
}, []);
42+
43+
const allScripts = filteredFiles.concat(subdirectories);
2244

2345
// Initialize a counter for the number of issues
2446
let issueCount = 0;
2547

2648
// Check if each .sh file is mentioned in the README.md
27-
shFiles.forEach(file => {
28-
if (!readme.includes(`### ${file}`)) {
49+
allScripts.forEach(file => {
50+
if (!readme.includes(`${headingLevel} ${file}`)) {
2951
console.log(`The file ${file} is not mentioned in the README.md`);
3052
issueCount++;
3153
}
3254
});
3355

34-
// Check that all .sh files follow the kebab-case naming convention
35-
shFiles.forEach(file => {
36-
if (!/^([a-z0-9]+-)*[a-z0-9]+\.sh$/.test(file)) {
56+
// Check that all files follow the kebab-case naming convention
57+
allScripts.forEach(file => {
58+
if (!/^([a-z0-9]+-)*[a-z0-9]+(\.[a-z0-9]+)*$/.test(file)) {
3759
console.log(`The file ${file} does not follow the kebab-case naming convention`);
3860
issueCount++;
3961
}
4062
});
4163

4264
// Check that all .sh files have execution permissions
43-
shFiles.forEach(file => {
65+
allScripts.forEach(file => {
66+
if (!file.endsWith('.sh')) {
67+
return;
68+
}
69+
4470
const filePath = path.join(directoryPath, file);
4571
const stats = fs.statSync(filePath);
4672
const isExecutable = (stats.mode & fs.constants.X_OK) !== 0;
@@ -52,15 +78,16 @@ shFiles.forEach(file => {
5278
});
5379

5480
// Extract the part of the README under the ## Scripts heading
55-
const scriptsSection = readme.split('## Scripts\n')[1];
81+
const scriptsSection = readme.split(`${parentHeading}\n`)[1];
5682

5783
// Extract all ### headings from the scripts section
58-
const headings = scriptsSection.match(/### .*/g);
84+
const regex = new RegExp(`${headingLevel} .*`, 'g');
85+
const headings = scriptsSection.match(regex);
5986

6087
// Check that all scripts mentioned in the README.md actually exist in the repository
6188
headings.forEach(heading => {
62-
const script = heading.slice(4); // Remove the '### ' prefix
63-
if (!shFiles.includes(script)) {
89+
const script = heading.slice(headingLevel.length + 1); // Remove the '### ' prefix
90+
if (!allScripts.includes(script)) {
6491
console.log(`The script ${script} is mentioned in the README.md but does not exist in the repository`);
6592
issueCount++;
6693
}
@@ -74,7 +101,7 @@ const shortWords = {
74101
'orgs': 'organizations'
75102
};
76103

77-
shFiles.forEach(file => {
104+
allScripts.forEach(file => {
78105
Object.keys(shortWords).forEach(word => {
79106
const regex = new RegExp(`\\b${word}\\b`, 'g');
80107
if (regex.test(file)) {

.github/workflows/lint-readme.yml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,15 @@ jobs:
1515
uses: actions/checkout@v4
1616

1717
- name: Lint ./gh-cli/README.md
18-
run: node ./.github/scripts/lint-gh-cli-readme.js
18+
run: node ./.github/scripts/lint-readme.js
19+
20+
lint-scripts-readme:
21+
name: Lint ./scripts/README.md
22+
runs-on: ubuntu-latest
23+
24+
steps:
25+
- name: Checkout code
26+
uses: actions/checkout@v4
27+
28+
- name: Lint ./scripts/README.md
29+
run: node ./.github/scripts/lint-readme.js ./scripts '##' '# scripts'

scripts/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ Configuration values to change in the script:
3232
- `gitEmail` = If using a GitHub App, combine the App's user ID (⚠️ this is different than App ID!) and name to form an email like: `149130343+josh-issueops-bot[bot]@users.noreply.github.com`. You can find the App's user ID number by calling: `gh api '/users/josh-issueops-bot[bot]' --jq .id`
3333
- `overwrite`: use `false` or `true` on whether it should overwrite the existing `dependabot.yml` file
3434

35-
## ado_workitems_to_github_issues.ps1
35+
## ado-workitems-to-github-issues.ps1
3636

3737
Migrate work items from Azure DevOps to GitHub issues - this just links out to a [separate repo](https://github.com/joshjohanning/ado_workitems_to_github_issues)
3838

@@ -87,7 +87,7 @@ My use case is to use this list to determine who needs to be added to a organiza
8787
1. Run: `./new-users-to-add-to-project.sh <org> <repo> <file>`
8888
2. Don't delete the `<file>` as it functions as your user database
8989

90-
## migrate-maven-packages-between-github-instances
90+
## migrate-maven-packages-between-github-instances.sh
9191

9292
Migrate Maven packages in GitHub Packages from one GitHub organization to another.
9393

@@ -103,7 +103,7 @@ Migrate npm packages in GitHub Packages from one GitHub organization to another.
103103
2. Define the target GitHub PAT env var: `export GH_TARGET_PAT=ghp_abc` (must have at least `write:packages`, `read:org`, `repo` scope)
104104
3. Run: `./migrate-maven-packages-between-github-instances.sh joshjohanning-org github.com joshjohanning-emu github.com`
105105

106-
## migrate-nuget-packages-between-github-instances
106+
## migrate-nuget-packages-between-github-instances.sh
107107

108108
Migrate NuGet packages in GitHub Packages from one GitHub organization to another. Runs script from upstream [source](https://github.com/joshjohanning/github-packages-migrate-nuget-packages-between-github-instances).
109109

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
# see: https://github.com/joshjohanning/ado_workitems_to_github_issues/blob/main/ado_workitems_to_github_issues.ps1
1+
# see: https://github.com/joshjohanning/ado_workitems_to_github_issues/blob/main/ado_workitems_to_github_issues.ps1

0 commit comments

Comments
 (0)