Skip to content

Commit

Permalink
ci: adjust contributors logic to include new crowdin project and homa…
Browse files Browse the repository at this point in the history
…rr repository (#178)

Co-authored-by: Meierschlumpf <[email protected]>
  • Loading branch information
Meierschlumpf and Meierschlumpf authored Jan 29, 2025
1 parent 992b8c1 commit e11805c
Show file tree
Hide file tree
Showing 8 changed files with 134 additions and 89 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/dump-api-data.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ on:
workflow_dispatch:

env:
HOMARR_DOCUMENTATION_GH_TOKEN: "${{ secrets.HOMARR_DOCUMENTATION_GH_TOKEN }}"
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
HOMARR_CROWDIN_TOKEN: "${{ secrets.HOMARR_CROWDIN_TOKEN }}"
HOMARR_LABS_CROWDIN_TOKEN: "${{ secrets.HOMARR_LABS_CROWDIN_TOKEN }}"

permissions:
contents: write
Expand All @@ -17,7 +18,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [20]
node-version: [22]
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v2
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"serve": "docusaurus serve",
"write-translations": "docusaurus write-translations",
"write-heading-ids": "docusaurus write-heading-ids",
"api-dump-contributors": "node ./scripts/dump-contributors.js"
"api-dump-contributors": "node ./scripts/dump-contributors.mjs"
},
"dependencies": {
"@dipakparmar/docusaurus-plugin-umami": "^2.1.2",
Expand Down
74 changes: 0 additions & 74 deletions scripts/dump-contributors.js

This file was deleted.

103 changes: 103 additions & 0 deletions scripts/dump-contributors.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { z } from 'zod';
import fs from 'fs/promises';

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

const schema = z.object({
GITHUB_TOKEN: z.string().nonempty(),
HOMARR_CROWDIN_TOKEN: z.string().nonempty(),
HOMARR_LABS_CROWDIN_TOKEN: z.string().nonempty(),
});

const env = schema.parse(process.env);

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();

const dataSchema = z.array(
z.object({
login: z.string(),
avatar_url: z.string().url(),
contributions: z.number(),
})
);

return dataSchema.parse(data);
};

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

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

const dataSchema = z.object({
data: z.array(
z.object({
data: z.object({
username: z.string(),
avatarUrl: z.string().url(),
}),
})
),
});

const contributionsData = dataSchema.parse(data);

return contributionsData.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/contributions.json', JSON.stringify(distinctGithubContributors));

for (const { projectId, tokenName } of sources.crowdin) {
crowdinContributors.push(...(await fetchCrowdinMembers(projectId, tokenName)));
}
const distinctCrowdinContributors = crowdinContributors.filter(
distinctBy((contributor) => contributor.username)
);
await fs.writeFile(
'./static/data/translation-contributions.json',
JSON.stringify(distinctCrowdinContributors)
);
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,37 @@ type Contributor = {
};

// do not add any real users here
const blacklistedUsernames = ['deepsource-autofix[bot]', 'deepsource-io[bot]', 'renovate[bot]', 'dependabot[bot]'];
const blacklistedUsernames = [
'deepsource-autofix[bot]',
'deepsource-io[bot]',
'renovate[bot]',
'dependabot[bot]',
];

export const CodeContributorList = () => {
const [contributors, setContributors] = useState<Contributor[]>([]);

useEffect(() => {
fetch('./data/contributions.json').then(async (response) => {
fetch('/data/contributions.json').then(async (response) => {
const data = await response.json();
setContributors(data.filter((contributor: Contributor) => !blacklistedUsernames.includes(contributor.login)));
setContributors(
data.filter((contributor: Contributor) => !blacklistedUsernames.includes(contributor.login))
);
});
}, []);

return (
<div className={'flex flex-wrap gap-3'}>
{contributors.map((contributor: Contributor) => (
<div className={'flex flex-col items-center w-24'}>
<img className={'w-24 h-24 aspect-square rounded mb-2'} src={contributor.avatar_url} alt={''} />
<h6 className={"truncate text-nowrap max-w-full"}>{contributor.login}</h6>
<img
className={'w-24 h-24 aspect-square rounded mb-2'}
src={contributor.avatar_url}
alt={''}
/>
<h6 className={'truncate text-nowrap max-w-full'}>{contributor.login}</h6>
</div>
))}
</div>
);
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const TranslationContributorList = () => {
const [contributors, setContributors] = useState<Contributor[]>([]);

useEffect(() => {
fetch('./data/translation-contributions.json').then(async (response) => {
fetch('/data/translation-contributions.json').then(async (response) => {
const data = await response.json();
setContributors(data);
});
Expand All @@ -19,10 +19,14 @@ export const TranslationContributorList = () => {
<div className={'flex flex-wrap gap-3'}>
{contributors.map((contributor: Contributor) => (
<div className={'flex flex-col items-center w-24'}>
<img className={'w-24 h-24 aspect-square rounded mb-2'} src={contributor.avatarUrl} alt={''} />
<h6 className={"truncate text-nowrap max-w-full"}>{contributor.username}</h6>
<img
className={'w-24 h-24 aspect-square rounded mb-2'}
src={contributor.avatarUrl}
alt={''}
/>
<h6 className={'truncate text-nowrap max-w-full'}>{contributor.username}</h6>
</div>
))}
</div>
);
};
};
2 changes: 1 addition & 1 deletion static/data/contributions.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
[{"login":"ajnart","avatar_url":"https://avatars.githubusercontent.com/u/49837342?v=4"},{"login":"manuel-rw","avatar_url":"https://avatars.githubusercontent.com/u/30572287?v=4"},{"login":"Meierschlumpf","avatar_url":"https://avatars.githubusercontent.com/u/63781622?v=4"},{"login":"renovate[bot]","avatar_url":"https://avatars.githubusercontent.com/in/2740?v=4"},{"login":"SeDemal","avatar_url":"https://avatars.githubusercontent.com/u/26098587?v=4"},{"login":"walkxcode","avatar_url":"https://avatars.githubusercontent.com/u/71191962?v=4"},{"login":"LarveyOfficial","avatar_url":"https://avatars.githubusercontent.com/u/39219859?v=4"},{"login":"c00ldude1oo","avatar_url":"https://avatars.githubusercontent.com/u/15677803?v=4"},{"login":"InterN0te","avatar_url":"https://avatars.githubusercontent.com/u/10882916?v=4"},{"login":"Aimsucks","avatar_url":"https://avatars.githubusercontent.com/u/1828486?v=4"},{"login":"JannesV","avatar_url":"https://avatars.githubusercontent.com/u/5984244?v=4"},{"login":"MauriceNino","avatar_url":"https://avatars.githubusercontent.com/u/18658092?v=4"},{"login":"hillaliy","avatar_url":"https://avatars.githubusercontent.com/u/950010?v=4"},{"login":"Skeeww","avatar_url":"https://avatars.githubusercontent.com/u/9639992?v=4"},{"login":"deepsource-autofix[bot]","avatar_url":"https://avatars.githubusercontent.com/in/57168?v=4"},{"login":"RichyHBM","avatar_url":"https://avatars.githubusercontent.com/u/5472275?v=4"},{"login":"Bonfire","avatar_url":"https://avatars.githubusercontent.com/u/5704760?v=4"},{"login":"wieli99","avatar_url":"https://avatars.githubusercontent.com/u/46794825?v=4"},{"login":"ishaanparlikar","avatar_url":"https://avatars.githubusercontent.com/u/43013132?v=4"},{"login":"Zareix","avatar_url":"https://avatars.githubusercontent.com/u/29818713?v=4"},{"login":"tuggan","avatar_url":"https://avatars.githubusercontent.com/u/4325608?v=4"},{"login":"dependabot[bot]","avatar_url":"https://avatars.githubusercontent.com/in/29110?v=4"},{"login":"deepsource-io[bot]","avatar_url":"https://avatars.githubusercontent.com/in/16372?v=4"},{"login":"Spillebulle","avatar_url":"https://avatars.githubusercontent.com/u/46653946?v=4"},{"login":"tancak","avatar_url":"https://avatars.githubusercontent.com/u/11760749?v=4"},{"login":"spkesDE","avatar_url":"https://avatars.githubusercontent.com/u/1682314?v=4"},{"login":"j3lte","avatar_url":"https://avatars.githubusercontent.com/u/2557568?v=4"},{"login":"dslatt","avatar_url":"https://avatars.githubusercontent.com/u/5211001?v=4"},{"login":"Malong11-007","avatar_url":"https://avatars.githubusercontent.com/u/40298510?v=4"},{"login":"Lollyde","avatar_url":"https://avatars.githubusercontent.com/u/11347524?v=4"}]
[{"login":"ajnart","avatar_url":"https://avatars.githubusercontent.com/u/49837342?v=4"},{"login":"manuel-rw","avatar_url":"https://avatars.githubusercontent.com/u/30572287?v=4"},{"login":"Meierschlumpf","avatar_url":"https://avatars.githubusercontent.com/u/63781622?v=4"},{"login":"SeDemal","avatar_url":"https://avatars.githubusercontent.com/u/26098587?v=4"},{"login":"walkxcode","avatar_url":"https://avatars.githubusercontent.com/u/71191962?v=4"},{"login":"LarveyOfficial","avatar_url":"https://avatars.githubusercontent.com/u/39219859?v=4"},{"login":"c00ldude1oo","avatar_url":"https://avatars.githubusercontent.com/u/15677803?v=4"},{"login":"InterN0te","avatar_url":"https://avatars.githubusercontent.com/u/10882916?v=4"},{"login":"Aimsucks","avatar_url":"https://avatars.githubusercontent.com/u/1828486?v=4"},{"login":"JannesV","avatar_url":"https://avatars.githubusercontent.com/u/5984244?v=4"},{"login":"MauriceNino","avatar_url":"https://avatars.githubusercontent.com/u/18658092?v=4"},{"login":"hillaliy","avatar_url":"https://avatars.githubusercontent.com/u/950010?v=4"},{"login":"Skeeww","avatar_url":"https://avatars.githubusercontent.com/u/9639992?v=4"},{"login":"RichyHBM","avatar_url":"https://avatars.githubusercontent.com/u/5472275?v=4"},{"login":"Bonfire","avatar_url":"https://avatars.githubusercontent.com/u/5704760?v=4"},{"login":"wieli99","avatar_url":"https://avatars.githubusercontent.com/u/46794825?v=4"},{"login":"ishaanparlikar","avatar_url":"https://avatars.githubusercontent.com/u/43013132?v=4"},{"login":"Zareix","avatar_url":"https://avatars.githubusercontent.com/u/29818713?v=4"},{"login":"tuggan","avatar_url":"https://avatars.githubusercontent.com/u/4325608?v=4"},{"login":"Spillebulle","avatar_url":"https://avatars.githubusercontent.com/u/46653946?v=4"},{"login":"tancak","avatar_url":"https://avatars.githubusercontent.com/u/11760749?v=4"},{"login":"spkesDE","avatar_url":"https://avatars.githubusercontent.com/u/1682314?v=4"},{"login":"j3lte","avatar_url":"https://avatars.githubusercontent.com/u/2557568?v=4"},{"login":"dslatt","avatar_url":"https://avatars.githubusercontent.com/u/5211001?v=4"},{"login":"Malong11-007","avatar_url":"https://avatars.githubusercontent.com/u/40298510?v=4"},{"login":"MaienM","avatar_url":"https://avatars.githubusercontent.com/u/583129?v=4"},{"login":"toineenzo","avatar_url":"https://avatars.githubusercontent.com/u/4921397?v=4"},{"login":"Lollyde","avatar_url":"https://avatars.githubusercontent.com/u/11347524?v=4"},{"login":"Havock94","avatar_url":"https://avatars.githubusercontent.com/u/7635248?v=4"},{"login":"Lumilias","avatar_url":"https://avatars.githubusercontent.com/u/10852161?v=4"},{"login":"marius-arch","avatar_url":"https://avatars.githubusercontent.com/u/72494359?v=4"},{"login":"Momcilo42","avatar_url":"https://avatars.githubusercontent.com/u/10118137?v=4"},{"login":"stark1tty","avatar_url":"https://avatars.githubusercontent.com/u/69326376?v=4"},{"login":"No-Maines-Land","avatar_url":"https://avatars.githubusercontent.com/u/20687725?v=4"},{"login":"NormanJS","avatar_url":"https://avatars.githubusercontent.com/u/83409549?v=4"},{"login":"Rikpat","avatar_url":"https://avatars.githubusercontent.com/u/33869814?v=4"},{"login":"SR3u","avatar_url":"https://avatars.githubusercontent.com/u/2380522?v=4"},{"login":"souravghosh01","avatar_url":"https://avatars.githubusercontent.com/u/37548139?v=4"},{"login":"StefanB7","avatar_url":"https://avatars.githubusercontent.com/u/22056509?v=4"},{"login":"devtobi","avatar_url":"https://avatars.githubusercontent.com/u/28538704?v=4"},{"login":"TyxTang","avatar_url":"https://avatars.githubusercontent.com/u/90897955?v=4"},{"login":"VinnyVynce","avatar_url":"https://avatars.githubusercontent.com/u/19630511?v=4"},{"login":"Willy-JL","avatar_url":"https://avatars.githubusercontent.com/u/49810075?v=4"},{"login":"anonysoul","avatar_url":"https://avatars.githubusercontent.com/u/105715150?v=4"},{"login":"cospeedster","avatar_url":"https://avatars.githubusercontent.com/u/52749645?v=4"},{"login":"diederbert","avatar_url":"https://avatars.githubusercontent.com/u/162878798?v=4"},{"login":"digdilem","avatar_url":"https://avatars.githubusercontent.com/u/4052275?v=4"},{"login":"dinghino","avatar_url":"https://avatars.githubusercontent.com/u/14729459?v=4"},{"login":"gfomichev","avatar_url":"https://avatars.githubusercontent.com/u/1596146?v=4"},{"login":"gnattu","avatar_url":"https://avatars.githubusercontent.com/u/12995396?v=4"},{"login":"tuxpizza","avatar_url":"https://avatars.githubusercontent.com/u/84710786?v=4"},{"login":"huanga","avatar_url":"https://avatars.githubusercontent.com/u/732970?v=4"},{"login":"taos15","avatar_url":"https://avatars.githubusercontent.com/u/122130728?v=4"},{"login":"arghyadipchak","avatar_url":"https://avatars.githubusercontent.com/u/32430374?v=4"},{"login":"AuthorShin","avatar_url":"https://avatars.githubusercontent.com/u/4959043?v=4"},{"login":"benniblot","avatar_url":"https://avatars.githubusercontent.com/u/47495914?v=4"},{"login":"bebsworthy","avatar_url":"https://avatars.githubusercontent.com/u/5266759?v=4"},{"login":"catrielmuller","avatar_url":"https://avatars.githubusercontent.com/u/2272323?v=4"},{"login":"Vysp3r","avatar_url":"https://avatars.githubusercontent.com/u/62019735?v=4"},{"login":"singular0","avatar_url":"https://avatars.githubusercontent.com/u/1925883?v=4"},{"login":"diogovalentte","avatar_url":"https://avatars.githubusercontent.com/u/49578155?v=4"},{"login":"codezninja","avatar_url":"https://avatars.githubusercontent.com/u/4400773?v=4"},{"login":"fabricionaweb","avatar_url":"https://avatars.githubusercontent.com/u/15933?v=4"},{"login":"nyok1912","avatar_url":"https://avatars.githubusercontent.com/u/32163949?v=4"},{"login":"bo3bdo","avatar_url":"https://avatars.githubusercontent.com/u/5271380?v=4"},{"login":"hskrtich","avatar_url":"https://avatars.githubusercontent.com/u/1214484?v=4"},{"login":"ishults","avatar_url":"https://avatars.githubusercontent.com/u/7275442?v=4"},{"login":"jelliuk","avatar_url":"https://avatars.githubusercontent.com/u/4790959?v=4"},{"login":"Moohan","avatar_url":"https://avatars.githubusercontent.com/u/5982260?v=4"},{"login":"jbruell","avatar_url":"https://avatars.githubusercontent.com/u/31685172?v=4"},{"login":"JasonLeeB06","avatar_url":"https://avatars.githubusercontent.com/u/82266978?v=4"},{"login":"jeffersonraimon","avatar_url":"https://avatars.githubusercontent.com/u/80064475?v=4"},{"login":"joser93","avatar_url":"https://avatars.githubusercontent.com/u/6912089?v=4"},{"login":"justijndepover","avatar_url":"https://avatars.githubusercontent.com/u/9008623?v=4"},{"login":"krishnamuppaneni","avatar_url":"https://avatars.githubusercontent.com/u/4703366?v=4"},{"login":"oben01","avatar_url":"https://avatars.githubusercontent.com/u/22369027?v=4"}]
2 changes: 1 addition & 1 deletion static/data/translation-contributions.json

Large diffs are not rendered by default.

0 comments on commit e11805c

Please sign in to comment.