Skip to content

Commit 4d282fe

Browse files
committed
add github action to implement #1490 contributor image
Implements @skyash-dev's solution from the p5.js repository: - add a github action to generate the image in contributors-png.yml - add utils/contributors-png.js to use node & canvas to make an image - generate a pull request with the new updated image when the all contributors file is changed - add contributors.png to the README in the contributors section
1 parent 4206874 commit 4d282fe

File tree

3 files changed

+105
-0
lines changed

3 files changed

+105
-0
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
name: Generate Contributors PNG
2+
3+
on:
4+
push:
5+
paths:
6+
- '.all-contributorsrc'
7+
8+
jobs:
9+
genimage:
10+
if: github.ref == 'refs/heads/main' && github.repository == 'processing/processing4'
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@v3
14+
15+
- name: Setup Node
16+
uses: actions/setup-node@v4
17+
with:
18+
node-version: 20
19+
20+
- name: Install dependencies
21+
run: npm install canvas
22+
23+
- name: Run contributors-png generator
24+
run: node utils/contributors-png.js
25+
26+
- name: Reset all changes except contributors.png
27+
run: |
28+
git restore --staged .
29+
git add contributors.png
30+
git checkout -- .
31+
32+
- name: Create Pull Request
33+
uses: peter-evans/create-pull-request@v7
34+
env:
35+
ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }}
36+
with:
37+
commit-message: "Update contributors.png from .all-contributorsrc"
38+
branch: update-contributors-png
39+
title: "chore: update contributors.png from .all-contributorsrc"
40+
body: "This PR updates the contributors.png to reflect changes in .all-contributorsrc"
41+
add-paths: contributors.png
42+
token: ${{ secrets.ACCESS_TOKEN }}

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ For licensing information about the Processing website see the [processing-websi
6767
Copyright (c) 2015-now The Processing Foundation
6868

6969
## Contributors
70+
![Grid of avatars representing contributors to the Processing4 project](contributors.png)
71+
7072
See [CONTRIBUTORS.md](./CONTRIBUTORS.md) for a list of all contributors to the project.
7173

7274
This project follows the [all-contributors specification](https://github.com/all-contributors/all-contributors) and the [Emoji Key](https://all-contributors.github.io/emoji-key/) ✨ for contribution types. Detailed instructions on how to add yourself or add contribution emojis to your name are [here](https://github.com/processing/processing4/issues/839). You can also post an issue or comment on a pull request with the text: `@all-contributors please add @YOUR-USERNAME for THINGS` (where `THINGS` is a comma-separated list of entries from the [list of possible contribution types](https://all-contributors.github.io/emoji-key/)) and our nice bot will add you to [CONTRIBUTORS.md](./CONTRIBUTORS.md) automatically!

utils/contributors-png.js

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
const { createCanvas, loadImage } = require('canvas');
2+
const fs = require('fs');
3+
4+
const data = fs.readFileSync('.all-contributorsrc', 'utf-8');
5+
const parsed = JSON.parse(data);
6+
const contributors = parsed.contributors;
7+
8+
const AVATAR_SIZE = 50;
9+
const GAP = 4;
10+
const COLS = 40;
11+
const ROWS = Math.ceil(contributors.length / COLS);
12+
13+
const width = COLS * AVATAR_SIZE + (COLS - 1) * GAP;
14+
const height = ROWS * AVATAR_SIZE + (ROWS - 1) * GAP;
15+
16+
const canvas = createCanvas(width, height);
17+
const ctx = canvas.getContext('2d');
18+
19+
async function loadAvatar(url) {
20+
try {
21+
const res = await fetch(url);
22+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
23+
24+
const buffer = Buffer.from(await res.arrayBuffer());
25+
return await loadImage(buffer);
26+
} catch (err) {
27+
return null;
28+
}
29+
}
30+
31+
(async () => {
32+
for (let i = 0; i < contributors.length; i++) {
33+
const c = contributors[i];
34+
35+
const col = i % COLS;
36+
const row = Math.floor(i / COLS);
37+
38+
const x = col * (AVATAR_SIZE + GAP);
39+
const y = row * (AVATAR_SIZE + GAP);
40+
41+
const img = await loadAvatar(c.avatar_url);
42+
43+
ctx.save();
44+
ctx.beginPath();
45+
ctx.arc(
46+
x + AVATAR_SIZE / 2,
47+
y + AVATAR_SIZE / 2,
48+
AVATAR_SIZE / 2,
49+
0,
50+
Math.PI * 2
51+
);
52+
ctx.clip();
53+
54+
if (img) {
55+
ctx.drawImage(img, x, y, AVATAR_SIZE, AVATAR_SIZE);
56+
}
57+
ctx.restore();
58+
}
59+
60+
fs.writeFileSync('contributors.png', canvas.toBuffer('image/png'));
61+
})();

0 commit comments

Comments
 (0)