Skip to content

Commit 7b674a0

Browse files
harish-sethuramanmdjermanovicnzakas
authored
chore: automate adding sponsors section to readme (#56)
Co-authored-by: Milos Djermanovic <[email protected]> Co-authored-by: Nicholas C. Zakas <[email protected]>
1 parent 3d9f7ce commit 7b674a0

File tree

9 files changed

+194
-0
lines changed

9 files changed

+194
-0
lines changed

.github/workflows/update-readme.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
name: Data Fetch
2+
3+
on:
4+
schedule:
5+
- cron: "0 8 * * *" # Every day at 1am PDT
6+
workflow_dispatch:
7+
8+
jobs:
9+
build:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- name: Check out repo
13+
uses: actions/checkout@v4
14+
with:
15+
token: ${{ secrets.WORKFLOW_PUSH_BOT_TOKEN }}
16+
17+
- name: Set up Node.js
18+
uses: actions/setup-node@v4
19+
20+
- name: Install npm packages
21+
run: npm install --force
22+
23+
- name: Update README with latest team and sponsor data
24+
run: npm run build:readme
25+
26+
- name: Setup Git
27+
run: |
28+
git config user.name "GitHub Actions Bot"
29+
git config user.email "<[email protected]>"
30+
31+
- name: Save updated files
32+
run: |
33+
chmod +x ./tools/commit-readme.sh
34+
./tools/commit-readme.sh

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,11 @@ This repository is the home of the following packages:
99
- [`@eslint/object-schema`](packages/object-schema)
1010
- [`@eslint/config-array`](packages/config-array)
1111
- [`@eslint/compat`](packages/compat)
12+
13+
## Sponsors
14+
15+
The following companies, organizations, and individuals support ESLint's ongoing maintenance and development. [Become a Sponsor](https://eslint.org/donate) to get your logo on our README and website.
16+
17+
<!-- NOTE: This section is autogenerated. Do not manually edit.-->
18+
<!--sponsorsstart-->
19+
<!--sponsorsend-->

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"scripts": {
77
"test": "npm test --workspaces --if-present",
88
"build": "node scripts/build.js",
9+
"build:readme": "node tools/update-readme.js",
910
"lint": "eslint .",
1011
"lint:fix": "eslint --fix .",
1112
"fmt": "prettier --write .",
@@ -26,8 +27,10 @@
2627
"!(*.js)": "prettier --write --ignore-unknown"
2728
},
2829
"devDependencies": {
30+
"common-tags": "^1.8.2",
2931
"eslint": "^9.4.0",
3032
"eslint-config-eslint": "^11.0.0",
33+
"got": "^14.4.1",
3134
"lint-staged": "^15.2.0",
3235
"prettier": "^3.1.1",
3336
"yorkie": "^2.0.0"

packages/compat/README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,3 +186,11 @@ module.exports = [
186186
## License
187187
188188
Apache 2.0
189+
190+
## Sponsors
191+
192+
The following companies, organizations, and individuals support ESLint's ongoing maintenance and development. [Become a Sponsor](https://eslint.org/donate) to get your logo on our README and website.
193+
194+
<!-- NOTE: This section is autogenerated. Do not manually edit.-->
195+
<!--sponsorsstart-->
196+
<!--sponsorsend-->

packages/config-array/README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,3 +338,11 @@ The design of this project was influenced by feedback on the ESLint RFC, and inc
338338
## License
339339

340340
Apache 2.0
341+
342+
## Sponsors
343+
344+
The following companies, organizations, and individuals support ESLint's ongoing maintenance and development. [Become a Sponsor](https://eslint.org/donate) to get your logo on our README and website.
345+
346+
<!-- NOTE: This section is autogenerated. Do not manually edit.-->
347+
<!--sponsorsstart-->
348+
<!--sponsorsend-->

packages/migrate-config/README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,11 @@ This tells ESLint to search for all files ending with `.ts` when a directory is
8383
## License
8484

8585
Apache 2.0
86+
87+
## Sponsors
88+
89+
The following companies, organizations, and individuals support ESLint's ongoing maintenance and development. [Become a Sponsor](https://eslint.org/donate) to get your logo on our README and website.
90+
91+
<!-- NOTE: This section is autogenerated. Do not manually edit.-->
92+
<!--sponsorsstart-->
93+
<!--sponsorsend-->

packages/object-schema/README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,3 +222,11 @@ In this example, even though `date` is an optional key, it is required to be pre
222222
## License
223223

224224
Apache 2.0
225+
226+
## Sponsors
227+
228+
The following companies, organizations, and individuals support ESLint's ongoing maintenance and development. [Become a Sponsor](https://eslint.org/donate) to get your logo on our README and website.
229+
230+
<!-- NOTE: This section is autogenerated. Do not manually edit.-->
231+
<!--sponsorsstart-->
232+
<!--sponsorsend-->

tools/commit-readme.sh

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/bin/bash
2+
3+
#------------------------------------------------------------------------------
4+
# Commits the data files if any have changed
5+
#------------------------------------------------------------------------------
6+
7+
if [ -z "$(git status --porcelain)" ]; then
8+
echo "Data did not change."
9+
else
10+
echo "Data changed!"
11+
12+
# commit the result
13+
git add README.md packages/**/README.md
14+
git commit -m "docs: Update README sponsors"
15+
16+
# push back to source control
17+
git push origin HEAD
18+
fi

tools/update-readme.js

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/**
2+
* @fileoverview Script to update the README with sponsors details in all packages.
3+
*
4+
* node tools/update-readme.js
5+
*
6+
* @author Harish Kumar S S
7+
*/
8+
9+
//-----------------------------------------------------------------------------
10+
// Requirements
11+
//-----------------------------------------------------------------------------
12+
13+
import { readFileSync, readdirSync, writeFileSync } from "node:fs";
14+
import { stripIndents } from "common-tags";
15+
import got from "got";
16+
17+
//-----------------------------------------------------------------------------
18+
// Data
19+
//-----------------------------------------------------------------------------
20+
21+
const SPONSORS_URL =
22+
"https://raw.githubusercontent.com/eslint/eslint.org/main/src/_data/sponsors.json";
23+
24+
const README_FILE_PATHS = [
25+
"./README.md",
26+
...readdirSync("./packages").map(dir => `./packages/${dir}/README.md`),
27+
];
28+
29+
const heights = {
30+
gold: 96,
31+
silver: 64,
32+
bronze: 32,
33+
};
34+
35+
//-----------------------------------------------------------------------------
36+
// Helpers
37+
//-----------------------------------------------------------------------------
38+
39+
/**
40+
* Fetches the latest sponsors data from the website.
41+
* @returns {Object} The sponsors data object.
42+
*/
43+
async function fetchSponsorsData() {
44+
const data = await got(SPONSORS_URL).json();
45+
46+
// remove backers from sponsors list - not shown on readme
47+
delete data.backers;
48+
49+
return data;
50+
}
51+
52+
/**
53+
* Formats an array of sponsors into HTML for the readme.
54+
* @param {Array} sponsors The array of sponsors.
55+
* @returns {string} The HTML for the readme.
56+
*/
57+
function formatSponsors(sponsors) {
58+
const nonEmptySponsors = Object.keys(sponsors).filter(
59+
tier => sponsors[tier].length > 0,
60+
);
61+
62+
return stripIndents`<!--sponsorsstart-->
63+
${nonEmptySponsors
64+
.map(
65+
tier => `<h3>${tier[0].toUpperCase()}${tier.slice(1)} Sponsors</h3>
66+
<p>${sponsors[tier]
67+
.map(
68+
sponsor =>
69+
`<a href="${sponsor.url || "#"}"><img src="${sponsor.image}" alt="${sponsor.name}" height="${heights[tier]}"></a>`,
70+
)
71+
.join(" ")}</p>`,
72+
)
73+
.join("")}
74+
<!--sponsorsend-->`;
75+
}
76+
77+
//-----------------------------------------------------------------------------
78+
// Main
79+
//-----------------------------------------------------------------------------
80+
81+
(async () => {
82+
const allSponsors = await fetchSponsorsData();
83+
84+
README_FILE_PATHS.forEach(filePath => {
85+
// read readme file
86+
const readme = readFileSync(filePath, "utf8");
87+
88+
let newReadme = readme.replace(
89+
/<!--sponsorsstart-->[\w\W]*?<!--sponsorsend-->/u,
90+
formatSponsors(allSponsors),
91+
);
92+
93+
// replace multiple consecutive blank lines with just one blank line
94+
newReadme = newReadme.replace(/(?<=^|\n)\n{2,}/gu, "\n");
95+
96+
// output to the files
97+
writeFileSync(filePath, newReadme, "utf8");
98+
});
99+
})();

0 commit comments

Comments
 (0)