Skip to content

ci: add update-contributors workflow #3014

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/automatic-approval.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ on:
jobs:
approve-automatic-prs:
runs-on: ubuntu-latest
if: github.actor_id == 158783068 || github.actor_id == 190541745 # Id of renovate bot and crowdin bot see https://api.github.com/users/homarr-renovate%5Bbot%5D and https://api.github.com/users/homarr-crowdin%5Bbot%5D
if: github.actor_id == 158783068 || github.actor_id == 190541745 || github.actor_id == 210161987 # Id of renovate bot and crowdin bot see https://api.github.com/users/homarr-renovate%5Bbot%5D and https://api.github.com/users/homarr-crowdin%5Bbot%5D and https://api.github.com/users/homarr-update-contributors%5Bbot%5D
steps:
- name: Checkout code
uses: actions/checkout@v4
Expand Down
70 changes: 70 additions & 0 deletions .github/workflows/update-contributors.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
name: Update Contributors

on:
schedule:
- cron: "0 12 * * FRI" # At 12:00 on Friday.
workflow_dispatch:

env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
CROWDIN_TOKEN: "${{ secrets.CROWDIN_UPDATE_CONTRIBUTORS_TOKEN }}"

permissions:
contents: write

jobs:
update-contributors:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [22]
steps:
- name: Obtain token
id: obtainToken
uses: tibdex/github-app-token@v2
with:
private_key: ${{ secrets.HOMARR_UPDATE_CONTRIBUTORS_PRIVATE_KEY }}
app_id: ${{ vars.HOMARR_UPDATE_CONTRIBUTORS_APP_ID }}

- name: Checkout repository
uses: actions/checkout@v4
env:
GITHUB_TOKEN: ${{ steps.obtainToken.outputs.token }}

- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}

- name: Run update script
run: node ./scripts/update-contributors.mjs

- name: Commit changes
env:
GITHUB_TOKEN: ${{ steps.obtainToken.outputs.token }}
run: |
git config --global user.email "210161987+homarr-update-contributors[bot]@users.noreply.github.com"
git config --global user.name "Homarr Update Contributors"
git add .
git commit -m "chore: update contributors"

- name: Create Pull Request
id: create-pull-request
uses: peter-evans/create-pull-request@v7
with:
token: ${{ steps.obtainToken.outputs.token }}
branch: update-contributors
base: dev
title: "chore: update contributors"
delete-branch: true
body: |
This PR updates the contributors list in the static-data directory.

- name: Install GitHub CLI
run: sudo apt-get install -y gh

- name: Enable auto-merge
env:
GITHUB_TOKEN: ${{ steps.obtainToken.outputs.token }}
run: |
gh pr merge ${{steps.create-pull-request.outputs.pull-request-number}} --auto --squash
73 changes: 73 additions & 0 deletions scripts/update-contributors.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import fs from "fs/promises";

const sources = {
crowdin: [
{ projectId: 534422 },
{ projectId: 742587 },
],
github: [
{ slug: "ajnart", repository: "homarr" },
{ slug: "homarr-labs", repository: "homarr" },
],
};

const env = {
GITHUB_TOKEN: process.env.GITHUB_TOKEN,
CROWDIN_TOKEN: process.env.CROWDIN_TOKEN,
};

const fetchGithubContributors = async (slug, repository) => {
const url = `https://api.github.com/repos/${slug}/${repository}/contributors?per_page=999`;
const options = {
method: "GET",
headers: {
Authorization: `Bearer ${env.GITHUB_TOKEN}`,
Accept: "application/vnd.github+json",
"X-GitHub-Api-Version": "2022-11-28",
},
};

const response = await fetch(url, options);
const data = await response.json();

return data;
};

const fetchCrowdinMembers = async (projectId) => {
const url = `https://crowdin.com/api/v2/projects/${projectId}/members`;
const options = {
method: "GET",
headers: {
Accept: "application/json",
Authorization: `Bearer ${env.CROWDIN_TOKEN}`,
},
};

const response = await fetch(url, options);
const data = await response.json();

return data.data.flatMap((data) => data.data);
};

const distinctBy = (callback) => (value, index, self) => {
return self.findIndex((item) => callback(item) === callback(value)) === index;
};

const githubContributors = [];
const crowdinContributors = [];

for (const { repository, slug } of sources.github) {
githubContributors.push(...(await fetchGithubContributors(slug, repository)));
}
const distinctGithubContributors = githubContributors
.filter(distinctBy((contributor) => contributor.login))
.sort((a, b) => b.contributions - a.contributions)
.map(({ contributions, ...props }) => props)
.filter((contributor) => !contributor.login.includes("[bot]"));
await fs.writeFile("./static-data/contributors.json", JSON.stringify(distinctGithubContributors));

for (const { projectId } of sources.crowdin) {
crowdinContributors.push(...(await fetchCrowdinMembers(projectId)));
}
const distinctCrowdinContributors = crowdinContributors.filter(distinctBy((contributor) => contributor.username));
await fs.writeFile("./static-data/translators.json", JSON.stringify(distinctCrowdinContributors));
Loading