From 75ef653afded7b5cc13f5323bb48c5a9eafb3e99 Mon Sep 17 00:00:00 2001 From: richerfu Date: Mon, 13 Jul 2026 10:06:47 +0800 Subject: [PATCH 1/2] Add github page deploy --- .github/workflows/website-preview-build.yml | 54 ++++++++++++++ .github/workflows/website-preview-deploy.yml | 76 ++++++++++++++++++++ .github/workflows/website.yml | 55 ++++++++++++++ website/api/index.html | 4 +- website/index.html | 4 +- website/src/api-docs.tsx | 5 +- website/src/main.tsx | 20 +++--- website/src/site-paths.ts | 13 ++++ website/vite.config.ts | 28 +++++++- 9 files changed, 242 insertions(+), 17 deletions(-) create mode 100644 .github/workflows/website-preview-build.yml create mode 100644 .github/workflows/website-preview-deploy.yml create mode 100644 .github/workflows/website.yml create mode 100644 website/src/site-paths.ts diff --git a/.github/workflows/website-preview-build.yml b/.github/workflows/website-preview-build.yml new file mode 100644 index 0000000..fc97489 --- /dev/null +++ b/.github/workflows/website-preview-build.yml @@ -0,0 +1,54 @@ +name: Build website preview + +on: + pull_request: + types: [ opened, reopened, synchronize ] + paths: + - "website/**" + - "package.json" + - "pnpm-lock.yaml" + - "pnpm-workspace.yaml" + - ".github/workflows/website-preview-build.yml" + +permissions: + contents: read + +concurrency: + group: website-preview-build-${{ github.event.pull_request.number }} + cancel-in-progress: true + +jobs: + build: + name: Build PR preview + runs-on: ubuntu-latest + + steps: + - name: Checkout PR + uses: actions/checkout@v7 + + - name: Setup pnpm + uses: pnpm/action-setup@v6 + with: + version: 10.24.0 + + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + node-version: 22 + cache: pnpm + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Build preview + env: + SITE_BASE_PATH: /${{ github.event.repository.name }}/pr-preview/pr-${{ github.event.pull_request.number }}/ + run: pnpm run website:build + + - name: Upload preview artifact + uses: actions/upload-artifact@v7 + with: + name: website-preview + path: website/dist + if-no-files-found: error + retention-days: 1 diff --git a/.github/workflows/website-preview-deploy.yml b/.github/workflows/website-preview-deploy.yml new file mode 100644 index 0000000..9eaa9c0 --- /dev/null +++ b/.github/workflows/website-preview-deploy.yml @@ -0,0 +1,76 @@ +name: Deploy website preview + +on: + workflow_run: + workflows: [ "Build website preview" ] + types: [ completed ] + pull_request_target: + types: [ closed ] + +permissions: + actions: read + contents: write + pull-requests: write + +jobs: + deploy: + name: Deploy PR preview + if: >- + github.event_name == 'workflow_run' && + github.event.workflow_run.conclusion == 'success' && + github.event.workflow_run.pull_requests[0].number != null + runs-on: ubuntu-latest + concurrency: + group: website-preview-${{ github.event.workflow_run.pull_requests[0].number }} + cancel-in-progress: false + + steps: + - name: Check whether PR is still open + id: pull-request + env: + GH_TOKEN: ${{ github.token }} + PR_NUMBER: ${{ github.event.workflow_run.pull_requests[0].number }} + run: | + state="$(gh api "repos/${GITHUB_REPOSITORY}/pulls/${PR_NUMBER}" --jq .state)" + if [[ "${state}" == "open" ]]; then + echo "is-open=true" >> "${GITHUB_OUTPUT}" + else + echo "is-open=false" >> "${GITHUB_OUTPUT}" + fi + + - name: Download preview artifact + if: steps.pull-request.outputs.is-open == 'true' + uses: actions/download-artifact@v8 + with: + name: website-preview + path: website/dist + github-token: ${{ github.token }} + run-id: ${{ github.event.workflow_run.id }} + + - name: Deploy preview + if: steps.pull-request.outputs.is-open == 'true' + uses: rossjrw/pr-preview-action@v1.8.1 + with: + action: deploy + source-dir: website/dist + preview-branch: gh-pages + pr-number: ${{ github.event.workflow_run.pull_requests[0].number }} + wait-for-pages-deployment: true + qr-code: false + + cleanup: + name: Remove closed PR preview + if: github.event_name == 'pull_request_target' + runs-on: ubuntu-latest + concurrency: + group: website-preview-${{ github.event.pull_request.number }} + cancel-in-progress: false + + steps: + - name: Remove preview + uses: rossjrw/pr-preview-action@v1.8.1 + with: + action: remove + preview-branch: gh-pages + pr-number: ${{ github.event.pull_request.number }} + comment: false diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml new file mode 100644 index 0000000..ffe898c --- /dev/null +++ b/.github/workflows/website.yml @@ -0,0 +1,55 @@ +name: Deploy website + +on: + push: + branches: [ main ] + paths: + - "website/**" + - "package.json" + - "pnpm-lock.yaml" + - "pnpm-workspace.yaml" + - ".github/workflows/website.yml" + workflow_dispatch: + +permissions: + contents: write + +concurrency: + group: website-production + cancel-in-progress: false + +jobs: + deploy: + name: Deploy production website + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v7 + + - name: Setup pnpm + uses: pnpm/action-setup@v6 + with: + version: 10.24.0 + + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + node-version: 22 + cache: pnpm + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Build website + env: + SITE_BASE_PATH: /${{ github.event.repository.name }}/ + run: pnpm run website:build + + - name: Deploy to GitHub Pages + uses: JamesIves/github-pages-deploy-action@v4.8.0 + with: + branch: gh-pages + folder: website/dist + clean-exclude: pr-preview + force: false diff --git a/website/api/index.html b/website/api/index.html index 8d5d487..d132e2d 100644 --- a/website/api/index.html +++ b/website/api/index.html @@ -4,8 +4,8 @@ - - + + zig-napi API diff --git a/website/index.html b/website/index.html index 1c5c18e..accb59d 100644 --- a/website/index.html +++ b/website/index.html @@ -7,8 +7,8 @@ name="description" content="Documentation website for zig-napi, a Zig toolkit for OpenHarmony and Node.js native addons." /> - - + + zig-napi diff --git a/website/src/api-docs.tsx b/website/src/api-docs.tsx index e4fc7a0..c49ce60 100644 --- a/website/src/api-docs.tsx +++ b/website/src/api-docs.tsx @@ -1,5 +1,6 @@ import { lastUpdatedByApiSection } from "virtual:api-last-updated"; import { apiMarkdownGroups, apiMarkdownSections, getApiSection } from "./content/api"; +import { siteHref, siteRelativePath } from "./site-paths"; export function ApiDocsPage() { const activeId = resolveActiveApiSectionId(); @@ -110,12 +111,12 @@ export function ApiDocsPage() { } function resolveActiveApiSectionId() { - const parts = window.location.pathname.split("/").filter(Boolean); + const parts = siteRelativePath().split("/").filter(Boolean); return parts[0] === "api" && parts[1] ? parts[1] : "overview"; } function apiHref(id: string) { - return id === "overview" ? "/api/" : `/api/${id}/`; + return siteHref(id === "overview" ? "api/" : `api/${id}/`); } function apiNavLinkClass(active: boolean, mode: "desktop" | "mobile" = "desktop") { diff --git a/website/src/main.tsx b/website/src/main.tsx index ed2ae9b..d35f634 100644 --- a/website/src/main.tsx +++ b/website/src/main.tsx @@ -6,6 +6,7 @@ import InstallSnippet from "./content/snippets/install.md"; import NodeSnippet from "./content/snippets/node.md"; import OpenHarmonySnippet from "./content/snippets/openharmony.md"; import TypesSnippet from "./content/snippets/types.md"; +import { siteHref, siteRelativePath } from "./site-paths"; import "./styles.css"; type Snippet = { @@ -140,9 +141,8 @@ function App() { } function resolveRoute(): SiteRoute { - return window.location.pathname === "/api" || window.location.pathname.startsWith("/api/") - ? "api" - : "home"; + const path = siteRelativePath(); + return path === "api" || path.startsWith("api/") ? "api" : "home"; } function HomePage({ route }: { route: SiteRoute }) { @@ -197,9 +197,9 @@ function SiteHeader({ route }: { route: SiteRoute }) {
- + zig-napi
@@ -207,7 +207,7 @@ function SiteHeader({ route }: { route: SiteRoute }) { className="flex items-center gap-5 text-sm text-(--color-muted)" aria-label="Primary navigation" > - + API @@ -233,7 +233,7 @@ function Hero() {

OpenHarmony and Node.js native addons

@@ -248,7 +248,7 @@ function Hero() { Start with ZON - + API Reference
@@ -256,7 +256,7 @@ function Hero() {
Zig source flowing through zig-napi into OpenHarmony libraries, Node addons, and TypeScript definitions
@@ -439,7 +439,7 @@ function ApiOverviewSection() { Use the API page when you need exact Zig signatures and wrapper behavior instead of the overview flow.

- + Open API Reference
diff --git a/website/src/site-paths.ts b/website/src/site-paths.ts new file mode 100644 index 0000000..b2d0b4b --- /dev/null +++ b/website/src/site-paths.ts @@ -0,0 +1,13 @@ +const siteBasePath = import.meta.env.BASE_URL; + +export function siteHref(path = "") { + return `${siteBasePath}${path.replace(/^\/+/, "")}`; +} + +export function siteRelativePath(pathname = window.location.pathname) { + const relativePath = pathname.startsWith(siteBasePath) + ? pathname.slice(siteBasePath.length) + : pathname; + + return relativePath.replace(/^\/+|\/+$/g, ""); +} diff --git a/website/vite.config.ts b/website/vite.config.ts index 87ba637..6dd2ca3 100644 --- a/website/vite.config.ts +++ b/website/vite.config.ts @@ -1,5 +1,5 @@ import { execFileSync } from "node:child_process"; -import { statSync } from "node:fs"; +import { copyFileSync, mkdirSync, statSync } from "node:fs"; import { dirname, resolve } from "node:path"; import { fileURLToPath } from "node:url"; import { defineConfig, type Plugin } from "vite"; @@ -8,6 +8,7 @@ import { voidReact } from "@void/react/plugin"; import tailwindcss from "@tailwindcss/vite"; const rootDir = dirname(fileURLToPath(import.meta.url)); +const siteBasePath = normalizeBasePath(process.env.SITE_BASE_PATH); const API_LAST_UPDATED_ID = "virtual:api-last-updated"; const RESOLVED_API_LAST_UPDATED_ID = `\0${API_LAST_UPDATED_ID}`; const apiMarkdownFiles = [ @@ -68,6 +69,29 @@ function apiLastUpdated(): Plugin { }; } +function apiStaticRoutes(): Plugin { + return { + name: "api-static-routes", + apply: "build", + closeBundle() { + const apiEntry = resolve(rootDir, "dist/api/index.html"); + + for (const [sectionId] of apiMarkdownFiles) { + if (sectionId === "overview") continue; + + const routeDir = resolve(rootDir, "dist/api", sectionId); + mkdirSync(routeDir, { recursive: true }); + copyFileSync(apiEntry, resolve(routeDir, "index.html")); + } + }, + }; +} + +function normalizeBasePath(value: string | undefined) { + const path = value?.trim().replace(/^\/+|\/+$/g, ""); + return path ? `/${path}/` : "/"; +} + function lastUpdatedIso(filePath: string) { try { const committed = execFileSync("git", ["log", "-1", "--format=%cI", "--", filePath], { @@ -84,6 +108,7 @@ function lastUpdatedIso(filePath: string) { } export default defineConfig({ + base: siteBasePath, plugins: [ voidReact(), voidMarkdown({ @@ -96,6 +121,7 @@ export default defineConfig({ }), apiFallback(), apiLastUpdated(), + apiStaticRoutes(), tailwindcss(), ], build: { From 732df545be0986deadca16ca49e5f43199759457 Mon Sep 17 00:00:00 2001 From: richerfu Date: Mon, 13 Jul 2026 10:13:06 +0800 Subject: [PATCH 2/2] Update config --- .github/workflows/website-preview-build.yml | 54 -------------- .github/workflows/website-preview-deploy.yml | 76 -------------------- .github/workflows/website.yml | 38 +++++++--- 3 files changed, 27 insertions(+), 141 deletions(-) delete mode 100644 .github/workflows/website-preview-build.yml delete mode 100644 .github/workflows/website-preview-deploy.yml diff --git a/.github/workflows/website-preview-build.yml b/.github/workflows/website-preview-build.yml deleted file mode 100644 index fc97489..0000000 --- a/.github/workflows/website-preview-build.yml +++ /dev/null @@ -1,54 +0,0 @@ -name: Build website preview - -on: - pull_request: - types: [ opened, reopened, synchronize ] - paths: - - "website/**" - - "package.json" - - "pnpm-lock.yaml" - - "pnpm-workspace.yaml" - - ".github/workflows/website-preview-build.yml" - -permissions: - contents: read - -concurrency: - group: website-preview-build-${{ github.event.pull_request.number }} - cancel-in-progress: true - -jobs: - build: - name: Build PR preview - runs-on: ubuntu-latest - - steps: - - name: Checkout PR - uses: actions/checkout@v7 - - - name: Setup pnpm - uses: pnpm/action-setup@v6 - with: - version: 10.24.0 - - - name: Setup Node.js - uses: actions/setup-node@v6 - with: - node-version: 22 - cache: pnpm - - - name: Install dependencies - run: pnpm install --frozen-lockfile - - - name: Build preview - env: - SITE_BASE_PATH: /${{ github.event.repository.name }}/pr-preview/pr-${{ github.event.pull_request.number }}/ - run: pnpm run website:build - - - name: Upload preview artifact - uses: actions/upload-artifact@v7 - with: - name: website-preview - path: website/dist - if-no-files-found: error - retention-days: 1 diff --git a/.github/workflows/website-preview-deploy.yml b/.github/workflows/website-preview-deploy.yml deleted file mode 100644 index 9eaa9c0..0000000 --- a/.github/workflows/website-preview-deploy.yml +++ /dev/null @@ -1,76 +0,0 @@ -name: Deploy website preview - -on: - workflow_run: - workflows: [ "Build website preview" ] - types: [ completed ] - pull_request_target: - types: [ closed ] - -permissions: - actions: read - contents: write - pull-requests: write - -jobs: - deploy: - name: Deploy PR preview - if: >- - github.event_name == 'workflow_run' && - github.event.workflow_run.conclusion == 'success' && - github.event.workflow_run.pull_requests[0].number != null - runs-on: ubuntu-latest - concurrency: - group: website-preview-${{ github.event.workflow_run.pull_requests[0].number }} - cancel-in-progress: false - - steps: - - name: Check whether PR is still open - id: pull-request - env: - GH_TOKEN: ${{ github.token }} - PR_NUMBER: ${{ github.event.workflow_run.pull_requests[0].number }} - run: | - state="$(gh api "repos/${GITHUB_REPOSITORY}/pulls/${PR_NUMBER}" --jq .state)" - if [[ "${state}" == "open" ]]; then - echo "is-open=true" >> "${GITHUB_OUTPUT}" - else - echo "is-open=false" >> "${GITHUB_OUTPUT}" - fi - - - name: Download preview artifact - if: steps.pull-request.outputs.is-open == 'true' - uses: actions/download-artifact@v8 - with: - name: website-preview - path: website/dist - github-token: ${{ github.token }} - run-id: ${{ github.event.workflow_run.id }} - - - name: Deploy preview - if: steps.pull-request.outputs.is-open == 'true' - uses: rossjrw/pr-preview-action@v1.8.1 - with: - action: deploy - source-dir: website/dist - preview-branch: gh-pages - pr-number: ${{ github.event.workflow_run.pull_requests[0].number }} - wait-for-pages-deployment: true - qr-code: false - - cleanup: - name: Remove closed PR preview - if: github.event_name == 'pull_request_target' - runs-on: ubuntu-latest - concurrency: - group: website-preview-${{ github.event.pull_request.number }} - cancel-in-progress: false - - steps: - - name: Remove preview - uses: rossjrw/pr-preview-action@v1.8.1 - with: - action: remove - preview-branch: gh-pages - pr-number: ${{ github.event.pull_request.number }} - comment: false diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml index ffe898c..9c6e93b 100644 --- a/.github/workflows/website.yml +++ b/.github/workflows/website.yml @@ -12,15 +12,17 @@ on: workflow_dispatch: permissions: - contents: write + contents: read + pages: write + id-token: write concurrency: - group: website-production + group: github-pages cancel-in-progress: false jobs: - deploy: - name: Deploy production website + build: + name: Build website runs-on: ubuntu-latest steps: @@ -41,15 +43,29 @@ jobs: - name: Install dependencies run: pnpm install --frozen-lockfile + - name: Configure GitHub Pages + id: pages + uses: actions/configure-pages@v6 + - name: Build website env: - SITE_BASE_PATH: /${{ github.event.repository.name }}/ + SITE_BASE_PATH: ${{ steps.pages.outputs.base_path }}/ run: pnpm run website:build - - name: Deploy to GitHub Pages - uses: JamesIves/github-pages-deploy-action@v4.8.0 + - name: Upload GitHub Pages artifact + uses: actions/upload-pages-artifact@v4 with: - branch: gh-pages - folder: website/dist - clean-exclude: pr-preview - force: false + path: website/dist + + deploy: + name: Deploy website + needs: build + runs-on: ubuntu-latest + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4