diff --git a/readme.md b/readme.md index dab957dd..00eb0a13 100644 --- a/readme.md +++ b/readme.md @@ -888,6 +888,7 @@ GitHub Readme Stats provides several environment variables that can be used to c * `CACHE_SECONDS`: This takes precedence over our cache minimum and maximum values and can circumvent these values for self-hosted instances. * `WHITELIST`: A comma-separated list of GitHub usernames that are allowed to access your instance. If this variable is not set, all usernames are allowed. * `GIST_WHITELIST`: A comma-separated list of GitHub gist IDs that are allowed to be accessed on your instance. If this variable is not set, all gist IDs are allowed. +* `EXCLUDE_REPO`: A comma-separated list of repositories that will be excluded from stats and top languages cards on your instance. This allows repository exclusion without exposing repository names in public URLs. This enhances privacy for self-hosted instances that include private repositories in stats cards. See [the Vercel documentation](https://vercel.com/docs/concepts/projects/environment-variables) on adding these environment variables to your Vercel instance. diff --git a/src/common/excludeRepo.js b/src/common/excludeRepo.js new file mode 100644 index 00000000..4e42ff8a --- /dev/null +++ b/src/common/excludeRepo.js @@ -0,0 +1,6 @@ +const excludeRepositories = process.env.EXCLUDE_REPO + ? process.env.EXCLUDE_REPO.split(",") + : []; + +export { excludeRepositories }; +export default excludeRepositories; diff --git a/src/fetchers/stats.js b/src/fetchers/stats.js index c54cdd93..5f56a7c4 100644 --- a/src/fetchers/stats.js +++ b/src/fetchers/stats.js @@ -1,4 +1,5 @@ // @ts-check + import axios from "axios"; import * as dotenv from "dotenv"; import githubUsernameRegex from "github-username-regex"; @@ -11,6 +12,7 @@ import { request, wrapTextMultiline, } from "../common/utils.js"; +import excludeRepositories from "../common/excludeRepo.js"; dotenv.config(); @@ -312,7 +314,8 @@ const fetchStats = async ( stats.contributedTo = user.repositoriesContributedTo.totalCount; // Retrieve stars while filtering out repositories to be hidden. - let repoToHide = new Set(exclude_repo); + const allExcludedRepos = [...exclude_repo, ...excludeRepositories]; + let repoToHide = new Set(allExcludedRepos); stats.totalStars = user.repositories.nodes .filter((data) => { diff --git a/src/fetchers/top-languages.js b/src/fetchers/top-languages.js index 485cc8b7..4490ef40 100644 --- a/src/fetchers/top-languages.js +++ b/src/fetchers/top-languages.js @@ -1,4 +1,5 @@ // @ts-check + import { retryer } from "../common/retryer.js"; import { CustomError, @@ -7,6 +8,7 @@ import { request, wrapTextMultiline, } from "../common/utils.js"; +import excludeRepositories from "../common/excludeRepo.js"; /** * @typedef {import("axios").AxiosRequestHeaders} AxiosRequestHeaders Axios request headers. @@ -99,11 +101,12 @@ const fetchTopLanguages = async ( let repoNodes = res.data.data.user.repositories.nodes; let repoToHide = {}; + const allExcludedRepos = [...exclude_repo, ...excludeRepositories]; // populate repoToHide map for quick lookup // while filtering out - if (exclude_repo) { - exclude_repo.forEach((repoName) => { + if (allExcludedRepos) { + allExcludedRepos.forEach((repoName) => { repoToHide[repoName] = true; }); }