Skip to content

Update Sponsors

Update Sponsors #1

Workflow file for this run

name: Update Sponsors
on:
schedule:
- cron: '0 3 * * 0' # weekly, Sunday 03:00 UTC
workflow_dispatch:
jobs:
update:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
token: ${{ secrets.SPONSORS_TOKEN }}
- name: Fetch sponsors and update README
env:
SPONSORS_TOKEN: ${{ secrets.SPONSORS_TOKEN }}
run: |
node --input-type=module <<'EOF'
import { readFileSync, writeFileSync } from 'fs';
const query = `
query {
user(login: "maathimself") {
sponsorshipsAsMaintainer(first: 100, includePrivate: false, activeOnly: false) {
nodes {
createdAt
isActive
sponsorEntity {
... on User { login avatarUrl(size: 64) url }
}
}
}
}
}
`;
const res = await fetch('https://api.github.com/graphql', {
method: 'POST',
headers: {
Authorization: `bearer ${process.env.SPONSORS_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ query }),
});
const { data, errors } = await res.json();
if (errors) { console.error(errors); process.exit(1); }
const ONE_MONTH_MS = 30 * 24 * 60 * 60 * 1000;
const now = Date.now();
const sponsors = data.user.sponsorshipsAsMaintainer.nodes
.filter(n => n.isActive || (now - new Date(n.createdAt).getTime()) <= ONE_MONTH_MS)
.map(n => n.sponsorEntity)
.filter(Boolean);
const esc = s => String(s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
const safeUrl = u => { try { const p = new URL(u).protocol; return p === 'https:' ? u : '#'; } catch { return '#'; } };
let section;
if (sponsors.length === 0) {
section = '_No sponsors yet — be the first!_';
} else {
section = sponsors
.map(s => `<a href="${safeUrl(s.url)}" title="${esc(s.login)}"><img src="${safeUrl(s.avatarUrl)}" width="48" height="48" alt="${esc(s.login)}" style="border-radius:50%;margin:4px"></a>`)
.join('\n');
}
const readme = readFileSync('README.md', 'utf8');
const updated = readme.replace(
/<!-- SPONSORS-START -->[\s\S]*?<!-- SPONSORS-END -->/,
`<!-- SPONSORS-START -->\n${section}\n<!-- SPONSORS-END -->`
);
const json = JSON.stringify(sponsors.map(s => ({
login: s.login,
avatarUrl: s.avatarUrl,
url: s.url,
})), null, 2);
writeFileSync('sponsors.json', json);
if (updated === readme) {
console.log('No changes.');
} else {
writeFileSync('README.md', updated);
console.log(`Updated: ${sponsors.length} sponsor(s).`);
}
EOF
- name: Commit and push if changed
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add README.md sponsors.json
git diff --quiet --cached || (
git commit -m "chore: update sponsors list" &&
git push
)