From 10aa0304e4747ae3ad1a70a70829778f8e2184aa Mon Sep 17 00:00:00 2001 From: JustMe Date: Mon, 12 Oct 2026 16:50:15 +0800 Subject: [PATCH] feat(web): separate build sources and localize time --- .woodpecker/dev-image.yml | 2 +- .woodpecker/release-backend.yml | 2 +- docs/frontend.md | 2 +- docs/ui-design.md | 2 +- server/Dockerfile | 12 +++++++---- web/src/build-info.d.ts | 6 ++++-- web/src/features/home/Home.tsx | 7 +++--- web/src/lib/buildInfo.ts | 38 ++++++++++++++++++++++++++++++++- web/vite.config.ts | 6 ++++-- 9 files changed, 60 insertions(+), 17 deletions(-) diff --git a/.woodpecker/dev-image.yml b/.woodpecker/dev-image.yml index aac864e..073e7a5 100644 --- a/.woodpecker/dev-image.yml +++ b/.woodpecker/dev-image.yml @@ -45,7 +45,7 @@ steps: - image="$ZOT_REGISTRY/justme/webdrop-api:dev-$sha" - dev_image="$ZOT_REGISTRY/justme/webdrop-api:dev" - build_time="$(date -u +%Y-%m-%dT%H:%M:%SZ)" - - buildah bud --layers --network host --format docker --platform linux/amd64 --build-arg "WEBDROP_BUILD_COMMIT=$CI_COMMIT_SHA" --build-arg "WEBDROP_BUILD_TAG=$build_tag" --build-arg "WEBDROP_BUILD_TIME=$build_time" --tag "$image" --file server/Dockerfile . + - buildah bud --layers --network host --format docker --platform linux/amd64 --build-arg "WEBDROP_FRONTEND_COMMIT=$CI_COMMIT_SHA" --build-arg "WEBDROP_FRONTEND_TAG=$build_tag" --build-arg "WEBDROP_BACKEND_COMMIT=$CI_COMMIT_SHA" --build-arg "WEBDROP_BACKEND_TAG=$build_tag" --build-arg "WEBDROP_BUILD_TIME=$build_time" --tag "$image" --file server/Dockerfile . - buildah tag "$image" "$dev_image" - buildah push "$image" "docker://$image" - buildah push "$dev_image" "docker://$dev_image" diff --git a/.woodpecker/release-backend.yml b/.woodpecker/release-backend.yml index e9e437a..fa902b7 100644 --- a/.woodpecker/release-backend.yml +++ b/.woodpecker/release-backend.yml @@ -58,7 +58,7 @@ steps: - latest_image="$ZOT_REGISTRY/justme/webdrop-api:latest" - build_commit="$(git rev-parse HEAD)" - build_time="$(date -u +%Y-%m-%dT%H:%M:%SZ)" - - buildah bud --layers --network host --format docker --platform linux/amd64 --build-arg "WEBDROP_BUILD_COMMIT=$build_commit" --build-arg "WEBDROP_BUILD_TAG=$release_tag" --build-arg "WEBDROP_BUILD_TIME=$build_time" --tag "$image" --file server/Dockerfile . + - buildah bud --layers --network host --format docker --platform linux/amd64 --build-arg "WEBDROP_FRONTEND_COMMIT=$build_commit" --build-arg "WEBDROP_FRONTEND_TAG=$release_tag" --build-arg "WEBDROP_BACKEND_COMMIT=$build_commit" --build-arg "WEBDROP_BACKEND_TAG=$release_tag" --build-arg "WEBDROP_BUILD_TIME=$build_time" --tag "$image" --file server/Dockerfile . - buildah tag "$image" "$latest_image" - buildah push "$image" "docker://$image" - buildah push "$latest_image" "docker://$latest_image" diff --git a/docs/frontend.md b/docs/frontend.md index eb0a1ac..b3de1ca 100644 --- a/docs/frontend.md +++ b/docs/frontend.md @@ -20,7 +20,7 @@ **依赖策略**:新增运行时依赖需要书面理由(解决什么、为何不能自写、体积)。不引入 UI 组件库、动画库、图标库、日期库。依赖越少,越容易审计;前端是整个方案的信任根。 -生产构建将 `web/package.json` 的版本和构建时注入的 commit、tag、UTC 时间编译进前端,首页右下角展示。部署构建通过 `WEBDROP_BUILD_COMMIT`、`WEBDROP_BUILD_TAG`、`WEBDROP_BUILD_TIME` 提供元数据;本地构建没有 CI 环境时尝试读取 Git,时间取本次构建时间。 +生产构建将 `web/package.json` 的版本、前后端各自的 commit/tag 和 UTC 构建时间编译进前端,首页右下角将时间换算为 Asia/Shanghai 并格式化为 `yyyy-MM-dd HH:mm`。部署构建通过 `WEBDROP_FRONTEND_COMMIT`、`WEBDROP_FRONTEND_TAG`、`WEBDROP_BACKEND_COMMIT`、`WEBDROP_BACKEND_TAG`、`WEBDROP_BUILD_TIME` 提供元数据;本地构建没有 CI 环境时尝试读取 Git,时间取本次构建时间。 ## 2. 目录与分层 diff --git a/docs/ui-design.md b/docs/ui-design.md index 3bff32b..ed83657 100644 --- a/docs/ui-design.md +++ b/docs/ui-design.md @@ -138,7 +138,7 @@ WebDrop 是**暂存区**,不是聊天室:内容按类型与待办动作组织, 首页把「临时分享」与「设备频道」作为两个并列入口:前者用于发一段临时文本或文件,后者用于多设备长期同步。 -主页右上角提供外观菜单,可跟随系统或切换亮色/暗色。右下角显示构建来源:前端包版本、构建 tag、commit 与 UTC 构建时间;这些值来自构建环境,无法取得时如实显示「未标记」或「未知」。 +主页右上角提供外观菜单,可跟随系统或切换亮色/暗色。右下角分别显示前端和后端的 tag 与短 commit hash,并显示换算为上海时间的构建时间(`yyyy-MM-dd HH:mm`);前端还显示包版本。无法取得 tag 时如实显示「未标记」。 ``` ┌──────────────────────────────────┐ diff --git a/server/Dockerfile b/server/Dockerfile index c91bc7e..2bfca7a 100644 --- a/server/Dockerfile +++ b/server/Dockerfile @@ -5,11 +5,15 @@ COPY packages/core/package.json ./packages/core/package.json RUN cd web && npm ci --no-audit --no-fund COPY packages/core/ ./packages/core/ COPY web/ ./web/ -ARG WEBDROP_BUILD_COMMIT=unknown -ARG WEBDROP_BUILD_TAG=unknown +ARG WEBDROP_FRONTEND_COMMIT=unknown +ARG WEBDROP_FRONTEND_TAG=unknown +ARG WEBDROP_BACKEND_COMMIT=unknown +ARG WEBDROP_BACKEND_TAG=unknown ARG WEBDROP_BUILD_TIME=unknown -ENV WEBDROP_BUILD_COMMIT=$WEBDROP_BUILD_COMMIT \ - WEBDROP_BUILD_TAG=$WEBDROP_BUILD_TAG \ +ENV WEBDROP_FRONTEND_COMMIT=$WEBDROP_FRONTEND_COMMIT \ + WEBDROP_FRONTEND_TAG=$WEBDROP_FRONTEND_TAG \ + WEBDROP_BACKEND_COMMIT=$WEBDROP_BACKEND_COMMIT \ + WEBDROP_BACKEND_TAG=$WEBDROP_BACKEND_TAG \ WEBDROP_BUILD_TIME=$WEBDROP_BUILD_TIME RUN npm run build --prefix web diff --git a/web/src/build-info.d.ts b/web/src/build-info.d.ts index a3e91f3..fe5c39a 100644 --- a/web/src/build-info.d.ts +++ b/web/src/build-info.d.ts @@ -1,6 +1,8 @@ declare const __WEBDROP_BUILD_INFO__: { readonly frontendVersion: string; - readonly commit: string; - readonly tag: string; + readonly frontendCommit: string; + readonly frontendTag: string; + readonly backendCommit: string; + readonly backendTag: string; readonly builtAt: string; }; diff --git a/web/src/features/home/Home.tsx b/web/src/features/home/Home.tsx index 4a3c9ab..d089b39 100644 --- a/web/src/features/home/Home.tsx +++ b/web/src/features/home/Home.tsx @@ -99,10 +99,9 @@ export function Home() { {createOpen ? setCreateOpen(false)} onCreated={open} /> : null} diff --git a/web/src/lib/buildInfo.ts b/web/src/lib/buildInfo.ts index c5380bc..8cad5a5 100644 --- a/web/src/lib/buildInfo.ts +++ b/web/src/lib/buildInfo.ts @@ -1 +1,37 @@ -export const buildInfo = __WEBDROP_BUILD_INFO__; +const shanghaiTime = new Intl.DateTimeFormat('en-CA', { + timeZone: 'Asia/Shanghai', + year: 'numeric', + month: '2-digit', + day: '2-digit', + hour: '2-digit', + minute: '2-digit', + hourCycle: 'h23', +}); + +function shortCommit(commit: string): string { + return commit === 'unknown' ? commit : commit.slice(0, 7); +} + +function knownTag(tag: string): string { + return tag === 'unknown' ? '' : tag; +} + +function formatShanghai(iso: string): string { + const date = new Date(iso); + if (Number.isNaN(date.getTime())) return '未知'; + + const parts = Object.fromEntries(shanghaiTime.formatToParts(date).map(({ type, value }) => [type, value])); + return `${parts.year}-${parts.month}-${parts.day} ${parts.hour}:${parts.minute}`; +} + +const source = __WEBDROP_BUILD_INFO__; + +export const buildInfo = { + frontendVersion: source.frontendVersion, + frontendCommit: shortCommit(source.frontendCommit), + frontendTag: knownTag(source.frontendTag), + backendCommit: shortCommit(source.backendCommit), + backendTag: knownTag(source.backendTag), + builtAt: source.builtAt, + builtAtShanghai: formatShanghai(source.builtAt), +}; diff --git a/web/vite.config.ts b/web/vite.config.ts index 779bdb1..7fb1ea7 100644 --- a/web/vite.config.ts +++ b/web/vite.config.ts @@ -17,8 +17,10 @@ function gitValue(...args: string[]): string { const buildInfo = { frontendVersion: webPackage.version, - commit: process.env.WEBDROP_BUILD_COMMIT ?? gitValue('rev-parse', '--short=12', 'HEAD'), - tag: process.env.WEBDROP_BUILD_TAG ?? gitValue('describe', '--tags', '--exact-match', 'HEAD'), + frontendCommit: process.env.WEBDROP_FRONTEND_COMMIT ?? gitValue('rev-parse', 'HEAD'), + frontendTag: process.env.WEBDROP_FRONTEND_TAG ?? gitValue('describe', '--tags', '--exact-match', 'HEAD'), + backendCommit: process.env.WEBDROP_BACKEND_COMMIT ?? gitValue('rev-parse', 'HEAD'), + backendTag: process.env.WEBDROP_BACKEND_TAG ?? gitValue('describe', '--tags', '--exact-match', 'HEAD'), builtAt: process.env.WEBDROP_BUILD_TIME ?? new Date().toISOString(), };