diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000..2e904959 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +github: [libredb] diff --git a/.github/workflows/update-sponsors.yml b/.github/workflows/update-sponsors.yml new file mode 100644 index 00000000..91648425 --- /dev/null +++ b/.github/workflows/update-sponsors.yml @@ -0,0 +1,98 @@ +name: Update Sponsors + +on: + schedule: + - cron: '0 6 * * 1' # Every Monday at 06:00 UTC + workflow_dispatch: + +permissions: + contents: write + +jobs: + update-sponsors: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Fetch sponsors and update README + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.SPONSORS_TOKEN }} + script: | + const fs = require('fs'); + + const result = await github.graphql(` + query { + organization(login: "libredb") { + sponsorshipsAsMaintainer(first: 100, activeOnly: true) { + nodes { + sponsorEntity { + ... on User { login, name, avatarUrl(size: 64), url } + ... on Organization { login, name, avatarUrl(size: 64), url } + } + tier { monthlyPriceInDollars } + } + } + } + } + `); + + const sponsors = result.organization.sponsorshipsAsMaintainer.nodes; + + const orgSponsors = sponsors.filter(s => s.tier.monthlyPriceInDollars >= 500); + const logoSponsors = sponsors.filter(s => s.tier.monthlyPriceInDollars >= 100 && s.tier.monthlyPriceInDollars < 500); + const backers = sponsors.filter(s => s.tier.monthlyPriceInDollars >= 20 && s.tier.monthlyPriceInDollars < 100); + const supporters = sponsors.filter(s => s.tier.monthlyPriceInDollars > 0 && s.tier.monthlyPriceInDollars < 20); + + const avatar = (entity, size) => + `${entity.login}`; + + const nameLink = entity => + `[${entity.name || entity.login}](${entity.url})`; + + let section = ''; + + if (orgSponsors.length > 0) { + section += '### Org Sponsors\n\n'; + section += orgSponsors.map(s => avatar(s.sponsorEntity, 80)).join(' ') + '\n\n'; + } + + if (logoSponsors.length > 0) { + section += '### Sponsors\n\n'; + section += logoSponsors.map(s => avatar(s.sponsorEntity, 56)).join(' ') + '\n\n'; + } + + if (backers.length > 0) { + section += '### Backers\n\n'; + section += backers.map(s => nameLink(s.sponsorEntity)).join(' · ') + '\n\n'; + } + + if (supporters.length > 0) { + section += '### Supporters\n\n'; + section += supporters.map(s => nameLink(s.sponsorEntity)).join(' · ') + '\n\n'; + } + + if (!section) { + section = '_Be the first to sponsor libredb-studio!_\n'; + } + + const readme = fs.readFileSync('README.md', 'utf8'); + const updated = readme.replace( + /[\s\S]*?/, + `\n${section}` + ); + + if (readme !== updated) { + fs.writeFileSync('README.md', updated); + console.log('README updated'); + } else { + console.log('No changes'); + } + + - name: Commit if changed + run: | + git config user.email "github-actions[bot]@users.noreply.github.com" + git config user.name "github-actions[bot]" + git add README.md + git diff --staged --quiet || git commit -m "chore: update sponsors list [skip ci]" + git diff HEAD~1..HEAD --quiet || git push diff --git a/README.md b/README.md index cfbb8b40..842235db 100644 --- a/README.md +++ b/README.md @@ -636,6 +636,25 @@ extraEnvFrom: --- +## Support + +libredb-studio is free and open source. If it helps you or your team, consider +[sponsoring the project](https://github.com/sponsors/libredb) — your support +funds maintenance, bug fixes, new database providers, and the ongoing +development of the open-source edition. + +[![Sponsor](https://img.shields.io/badge/Sponsor-libredb-ea4aaa?logo=githubsponsors&logoColor=white)](https://github.com/sponsors/libredb) + +--- + +## Sponsors + + +_Be the first to sponsor libredb-studio!_ + + +--- + ## Contributing We welcome contributions from the community! Whether it's a bug fix, a new feature, or documentation improvements: