This is an automated email from the ASF dual-hosted git repository.
hsluoyz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/casbin-website.git
The following commit(s) were added to refs/heads/master by this push:
new 2383ad8c feat: remove homepage GitHub API request (#469)
2383ad8c is described below
commit 2383ad8cf2936720027eeee46d21818180ad411f
Author: cooronx <[email protected]>
AuthorDate: Sat Apr 18 16:13:42 2026 +0800
feat: remove homepage GitHub API request (#469)
---
.github/workflows/master.yml | 3 +++
.github/workflows/pr_ci.yml | 3 +++
package.json | 1 +
scripts/generate-footer-stars.js | 46 +++++++++-----------------------
scripts/generate-homepage-release.js | 51 ++++++++++++++++++++++++++++++++++++
scripts/github-data-utils.js | 45 +++++++++++++++++++++++++++++++
src/data/latest-release.json | 5 ++++
src/pages/index.js | 16 +++++------
8 files changed, 126 insertions(+), 44 deletions(-)
diff --git a/.github/workflows/master.yml b/.github/workflows/master.yml
index 6c0091a4..ad7bbf4b 100644
--- a/.github/workflows/master.yml
+++ b/.github/workflows/master.yml
@@ -51,6 +51,9 @@ jobs:
- name: Generate footer stars
run: yarn generate:footer-stars
+ - name: Generate homepage release
+ run: yarn generate:homepage-release
+
- name: Build
run: yarn build
diff --git a/.github/workflows/pr_ci.yml b/.github/workflows/pr_ci.yml
index 3024e6ce..9a99b461 100644
--- a/.github/workflows/pr_ci.yml
+++ b/.github/workflows/pr_ci.yml
@@ -25,5 +25,8 @@ jobs:
- name: Generate footer stars
run: yarn generate:footer-stars
+ - name: Generate homepage release
+ run: yarn generate:homepage-release
+
- name: Build website
run: yarn build --locale en
diff --git a/package.json b/package.json
index d63b6281..4fc98b49 100644
--- a/package.json
+++ b/package.json
@@ -6,6 +6,7 @@
"scripts": {
"docusaurus": "docusaurus",
"generate:footer-stars": "node scripts/generate-footer-stars.js",
+ "generate:homepage-release": "node scripts/generate-homepage-release.js",
"start": "node scripts/start.js",
"build": "docusaurus build",
"swizzle": "docusaurus swizzle",
diff --git a/scripts/generate-footer-stars.js b/scripts/generate-footer-stars.js
index 0ab1a51a..83beca7f 100644
--- a/scripts/generate-footer-stars.js
+++ b/scripts/generate-footer-stars.js
@@ -1,5 +1,9 @@
-const fs = require("fs");
const path = require("path");
+const {
+ fetchGitHubJson,
+ readExistingJson,
+ writeJson,
+} = require("./github-data-utils");
const badges = require("../src/components/FooterMoreBadges/badges.json");
@@ -16,40 +20,14 @@ function getRepoKey(owner, repo) {
return `${owner}/${repo}`;
}
-function readExistingStars() {
- if (!fs.existsSync(outputPath)) {
- return null;
- }
-
- try {
- return JSON.parse(fs.readFileSync(outputPath, "utf8"));
- } catch {
- return null;
- }
-}
-
async function fetchStars() {
- const headers = {
- Accept: "application/vnd.github+json",
- "User-Agent": "casbin-website-footer-stars",
- };
-
- if (process.env.GITHUB_TOKEN) {
- headers.Authorization = `Bearer ${process.env.GITHUB_TOKEN}`;
- }
-
const results = await Promise.all(
badges.map(async({owner, repo}) => {
- const response = await
fetch(`https://api.github.com/repos/${owner}/${repo}`, {
- headers,
- });
-
- if (!response.ok) {
- const body = await response.text();
- throw new Error(`Failed to fetch stars for ${owner}/${repo}:
${response.status} ${body}`);
- }
-
- const data = await response.json();
+ const data = await fetchGitHubJson(
+ `https://api.github.com/repos/${owner}/${repo}`,
+ "casbin-website-footer-stars",
+ `stars for ${owner}/${repo}`
+ );
if (typeof data.stargazers_count !== "number") {
throw new Error(`Missing stargazers_count for ${owner}/${repo}`);
@@ -63,7 +41,7 @@ async function fetchStars() {
}
async function main() {
- const existingStars = readExistingStars();
+ const existingStars = readExistingJson(outputPath);
try {
const stars = await fetchStars();
@@ -72,7 +50,7 @@ async function main() {
stars,
};
- fs.writeFileSync(outputPath, `${JSON.stringify(payload, null, 2)}\n`);
+ writeJson(outputPath, payload);
process.stdout.write(`Updated footer stars at ${outputPath}\n`);
} catch (error) {
if (existingStars?.stars) {
diff --git a/scripts/generate-homepage-release.js
b/scripts/generate-homepage-release.js
new file mode 100644
index 00000000..17eef6ab
--- /dev/null
+++ b/scripts/generate-homepage-release.js
@@ -0,0 +1,51 @@
+const path = require("path");
+const {
+ fetchGitHubJson,
+ readExistingJson,
+ writeJson,
+} = require("./github-data-utils");
+
+const outputPath = path.join(__dirname, "..", "src", "data",
"latest-release.json");
+const fallbackTag = "v3.4.1";
+const fallbackUrl =
`https://github.com/apache/casbin/releases/tag/${fallbackTag}`;
+
+async function fetchLatestRelease() {
+ const data = await fetchGitHubJson(
+ "https://api.github.com/repos/casbin/casbin/releases/latest",
+ "casbin-website-homepage-release",
+ "latest homepage release"
+ );
+
+ return {
+ generatedAt: new Date().toISOString(),
+ tagName: data.tag_name || fallbackTag,
+ url: data.html_url || fallbackUrl,
+ };
+}
+
+async function main() {
+ const existingRelease = readExistingJson(outputPath);
+
+ try {
+ const payload = await fetchLatestRelease();
+ writeJson(outputPath, payload);
+ process.stdout.write(`Updated homepage release at ${outputPath}\n`);
+ } catch (error) {
+ if (existingRelease?.tagName && existingRelease?.url) {
+ process.stderr.write(`${error.message}\nUsing existing homepage release
JSON.\n`);
+ return;
+ }
+
+ writeJson(outputPath, {
+ generatedAt: new Date().toISOString(),
+ tagName: fallbackTag,
+ url: fallbackUrl,
+ });
+ process.stderr.write(`${error.message}\nUsing fallback homepage release
JSON.\n`);
+ }
+}
+
+main().catch((error) => {
+ process.stderr.write(`${error.stack || error}\n`);
+ process.exit(1);
+});
diff --git a/scripts/github-data-utils.js b/scripts/github-data-utils.js
new file mode 100644
index 00000000..081b275a
--- /dev/null
+++ b/scripts/github-data-utils.js
@@ -0,0 +1,45 @@
+const fs = require("fs");
+const path = require("path");
+
+function readExistingJson(filePath) {
+ if (!fs.existsSync(filePath)) {
+ return null;
+ }
+
+ try {
+ return JSON.parse(fs.readFileSync(filePath, "utf8"));
+ } catch {
+ return null;
+ }
+}
+
+function writeJson(filePath, payload) {
+ fs.mkdirSync(path.dirname(filePath), {recursive: true});
+ fs.writeFileSync(filePath, `${JSON.stringify(payload, null, 2)}\n`);
+}
+
+function getGitHubHeaders(userAgent) {
+ return {
+ Accept: "application/vnd.github+json",
+ "User-Agent": userAgent,
+ };
+}
+
+async function fetchGitHubJson(url, userAgent, errorLabel) {
+ const response = await fetch(url, {
+ headers: getGitHubHeaders(userAgent),
+ });
+
+ if (!response.ok) {
+ const body = await response.text();
+ throw new Error(`Failed to fetch ${errorLabel}: ${response.status}
${body}`);
+ }
+
+ return response.json();
+}
+
+module.exports = {
+ fetchGitHubJson,
+ readExistingJson,
+ writeJson,
+};
diff --git a/src/data/latest-release.json b/src/data/latest-release.json
new file mode 100644
index 00000000..f419b372
--- /dev/null
+++ b/src/data/latest-release.json
@@ -0,0 +1,5 @@
+{
+ "generatedAt": "2026-04-18T02:02:59.172Z",
+ "tagName": "v3.10.0",
+ "url": "https://github.com/apache/casbin/releases/tag/v3.10.0"
+}
diff --git a/src/pages/index.js b/src/pages/index.js
index 5c66b31e..b95671ad 100644
--- a/src/pages/index.js
+++ b/src/pages/index.js
@@ -1,4 +1,4 @@
-import React, {useEffect, useRef, useState} from "react";
+import React, {useEffect, useRef} from "react";
import clsx from "clsx";
import Layout from "@theme/Layout";
import Link from "@docusaurus/Link";
@@ -12,26 +12,22 @@ import useDocusaurusContext from
"@docusaurus/useDocusaurusContext";
import AnimatedText from "../components/AnimatedText";
import {Code, Zap} from "lucide-react";
import LogoCarousel from "@site/src/components/LogoCarousel";
+import latestReleaseData from "@site/src/data/latest-release.json";
function HomepageHeader() {
- const [latestVersion, setLatestVersion] = useState("v3.4.1");
const headerRef = useRef(null);
const haloRef = useRef(null);
const {siteConfig} = useDocusaurusContext();
const {customFields} = siteConfig;
+ const latestVersion = latestReleaseData.tagName || "v3.4.1";
+ const latestReleaseLink =
+ latestReleaseData.url ||
`https://github.com/apache/casbin/releases/tag/${latestVersion}`;
// Activate halo behavior for this header
useHeroCursorHalo(headerRef, haloRef);
- useEffect(() => {
- fetch("https://api.github.com/repos/casbin/casbin/releases/latest")
- .then(res => res.json())
- .then(data => setLatestVersion(data.tag_name || "v3.4.1"))
- .catch(() => setLatestVersion("v3.4.1"));
- }, []);
-
const pillText = customFields?.customMessage || `${latestVersion} Released`;
- const link = customFields?.customLink ||
`https://github.com/casbin/casbin/releases/tag/${latestVersion}`;
+ const link = customFields?.customLink || latestReleaseLink;
return (
<header ref={headerRef} className={clsx("hero hero--primary",
styles.heroBanner)}>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]