name: Sponsor Tier Sync on: workflow_dispatch: schedule: - cron: "17 * * * *" permissions: contents: write jobs: sync: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Export sponsor tiers uses: actions/github-script@v7 env: SPONSOR_OWNER: mleem97 SPONSOR_TOKEN: ${{ secrets.SPONSORS_READ_TOKEN }} with: github-token: ${{ secrets.SPONSORS_READ_TOKEN != '' && secrets.SPONSORS_READ_TOKEN || github.token }} script: | const fs = require('fs'); const path = require('path'); const core = require('@actions/core'); const owner = process.env.SPONSOR_OWNER || context.repo.owner; const now = new Date().toISOString(); const outDir = path.join(process.cwd(), 'sponsors'); const outFile = path.join(outDir, 'sponsors.json'); const emptyPayload = { generatedAt: now, owner, totals: { activeSponsors: 0, monthlyUsd: 0 }, tiers: {}, sponsors: [] }; fs.mkdirSync(outDir, { recursive: true }); const query = ` query($login: String!) { user(login: $login) { sponsorshipsAsMaintainer(first: 100, activeOnly: true) { nodes { sponsorEntity { __typename ... on User { login url } ... on Organization { login url } } tier { name monthlyPriceInDollars isOneTime } privacyLevel createdAt } } } } `; try { const result = await github.graphql(query, { login: owner }); const nodes = result?.user?.sponsorshipsAsMaintainer?.nodes || []; const sponsors = nodes .filter(n => n?.tier && !n.tier.isOneTime && n?.sponsorEntity?.login) .map(n => ({ login: n.sponsorEntity.login, url: n.sponsorEntity.url, tierName: n.tier.name, monthlyUsd: n.tier.monthlyPriceInDollars, privacyLevel: n.privacyLevel, createdAt: n.createdAt })) .sort((a, b) => b.monthlyUsd - a.monthlyUsd || a.login.localeCompare(b.login)); const tiers = {}; let monthlyUsd = 0; for (const s of sponsors) { monthlyUsd += s.monthlyUsd; if (!tiers[s.monthlyUsd]) { tiers[s.monthlyUsd] = { count: 0, sponsors: [] }; } tiers[s.monthlyUsd].count += 1; tiers[s.monthlyUsd].sponsors.push({ login: s.login, url: s.url, tierName: s.tierName }); } const payload = { generatedAt: now, owner, totals: { activeSponsors: sponsors.length, monthlyUsd }, tiers, sponsors }; fs.writeFileSync(outFile, JSON.stringify(payload, null, 2) + '\n', 'utf8'); core.notice(`Exported ${sponsors.length} active sponsors for ${owner}.`); } catch (error) { core.warning(`Sponsor export failed: ${error.message}`); fs.writeFileSync(outFile, JSON.stringify(emptyPayload, null, 2) + '\n', 'utf8'); } - name: Commit sponsor export run: | if [[ -n "$(git status --porcelain sponsors/sponsors.json)" ]]; then git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" git add sponsors/sponsors.json git commit -m "chore(sponsors): sync sponsor tiers" git push else echo "No sponsor changes detected." fi