From d6c3dbad8f86f58b190bd003bcb851cd1d64aa87 Mon Sep 17 00:00:00 2001 From: sunlei Date: Thu, 18 Jun 2026 12:17:59 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20=E5=A2=9E=E5=8A=A0NapCat=E4=B8=AD?= =?UTF-8?q?=E6=96=87=E6=A1=8C=E9=9D=A2=E6=B4=BE=E7=94=9F=E9=95=9C=E5=83=8F?= =?UTF-8?q?=E8=B5=84=E4=BA=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ci/napcat-desktop-cn/Dockerfile | 30 +++++++++++++ ci/napcat-desktop-cn/README.md | 20 +++++++++ ci/napcat-desktop-cn/verify.sh | 12 ++++++ .../napcat/napcat-desktop-cn-image.spec.ts | 43 +++++++++++++++++++ 4 files changed, 105 insertions(+) create mode 100644 ci/napcat-desktop-cn/Dockerfile create mode 100644 ci/napcat-desktop-cn/README.md create mode 100644 ci/napcat-desktop-cn/verify.sh create mode 100644 test/modules/qqbot/napcat/napcat-desktop-cn-image.spec.ts diff --git a/ci/napcat-desktop-cn/Dockerfile b/ci/napcat-desktop-cn/Dockerfile new file mode 100644 index 0000000..57ae97b --- /dev/null +++ b/ci/napcat-desktop-cn/Dockerfile @@ -0,0 +1,30 @@ +ARG NAPCAT_BASE_IMAGE= +FROM ${NAPCAT_BASE_IMAGE} + +USER root + +RUN set -eux; \ + apt-get update; \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + dbus-x11 \ + fontconfig \ + fonts-noto-cjk \ + fonts-wqy-microhei \ + locales \ + tzdata; \ + sed -i 's/^# *zh_CN.UTF-8 UTF-8/zh_CN.UTF-8 UTF-8/' /etc/locale.gen; \ + locale-gen zh_CN.UTF-8; \ + ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime; \ + echo Asia/Shanghai > /etc/timezone; \ + fc-cache -fv; \ + rm -rf /var/lib/apt/lists/* + +ENV LANG=zh_CN.UTF-8 \ + LC_ALL=zh_CN.UTF-8 \ + LANGUAGE=zh_CN:zh \ + TZ=Asia/Shanghai \ + HOME=/app \ + XDG_CONFIG_HOME=/app/.config \ + XDG_CACHE_HOME=/app/.cache \ + XDG_DATA_HOME=/app/.local/share \ + XDG_RUNTIME_DIR=/tmp/runtime-napcat diff --git a/ci/napcat-desktop-cn/README.md b/ci/napcat-desktop-cn/README.md new file mode 100644 index 0000000..a9c91bb --- /dev/null +++ b/ci/napcat-desktop-cn/README.md @@ -0,0 +1,20 @@ +# NapCat Chinese Desktop Runtime Image + +Build from the locally inspected upstream digest: + +```powershell +$baseImage = docker image inspect mlikiowa/napcat-docker:latest --format '{{index .RepoDigests 0}}' +if (-not $baseImage) { throw 'NapCat upstream image digest not found; pull and inspect the image before building.' } +docker build ` + --build-arg NAPCAT_BASE_IMAGE=$baseImage ` + -t kt-napcat-desktop-cn:desktop-cn-v1 ` + -f ci/napcat-desktop-cn/Dockerfile . +``` + +Verify: + +```powershell +docker run --rm kt-napcat-desktop-cn:desktop-cn-v1 sh /ci/napcat-desktop-cn/verify.sh +``` + +Record the final digest in `QQBOT_NAPCAT_IMAGE`. diff --git a/ci/napcat-desktop-cn/verify.sh b/ci/napcat-desktop-cn/verify.sh new file mode 100644 index 0000000..c53a247 --- /dev/null +++ b/ci/napcat-desktop-cn/verify.sh @@ -0,0 +1,12 @@ +#!/bin/sh +set -eu + +locale -a | grep -i '^zh_CN.utf8$' +locale | grep 'LANG=zh_CN.UTF-8' +test "$(cat /etc/timezone)" = "Asia/Shanghai" +fc-match "Noto Sans CJK SC" | grep -E 'Noto|WenQuanYi|wqy' +test "XDG_CONFIG_HOME=${XDG_CONFIG_HOME:-}" = "XDG_CONFIG_HOME=/app/.config" +test "XDG_CACHE_HOME=${XDG_CACHE_HOME:-}" = "XDG_CACHE_HOME=/app/.cache" +test "XDG_DATA_HOME=${XDG_DATA_HOME:-}" = "XDG_DATA_HOME=/app/.local/share" +test ! -e /.dockerenv +grep -q '^0::/$' /proc/1/cgroup diff --git a/test/modules/qqbot/napcat/napcat-desktop-cn-image.spec.ts b/test/modules/qqbot/napcat/napcat-desktop-cn-image.spec.ts new file mode 100644 index 0000000..1177910 --- /dev/null +++ b/test/modules/qqbot/napcat/napcat-desktop-cn-image.spec.ts @@ -0,0 +1,43 @@ +import { readFileSync } from 'fs'; +import { join } from 'path'; + +const repoRoot = join(__dirname, '../../../..'); + +/** + * Reads a repo file as UTF-8 text for static image asset assertions. + * @param relativePath - Repository-relative path under `Node/kt-template-online-api`. + */ +const readSource = (relativePath: string) => + readFileSync(join(repoRoot, relativePath), 'utf8'); + +describe('NapCat Chinese Desktop Runtime image assets', () => { + it('builds from an explicitly supplied pinned base image', () => { + const dockerfile = readSource('ci/napcat-desktop-cn/Dockerfile'); + expect(dockerfile).toContain('ARG NAPCAT_BASE_IMAGE='); + expect(dockerfile).toContain('FROM ${NAPCAT_BASE_IMAGE}'); + expect(dockerfile).not.toContain('mlikiowa/napcat-docker:latest'); + }); + + it('installs Chinese locale, fonts, timezone, DBus, and fontconfig cache', () => { + const dockerfile = readSource('ci/napcat-desktop-cn/Dockerfile'); + expect(dockerfile).toContain('zh_CN.UTF-8 UTF-8'); + expect(dockerfile).toContain('LANG=zh_CN.UTF-8'); + expect(dockerfile).toContain('LC_ALL=zh_CN.UTF-8'); + expect(dockerfile).toContain('Asia/Shanghai'); + expect(dockerfile).toMatch(/fonts-noto-cjk|fonts-wqy-microhei/); + expect(dockerfile).toContain('fontconfig'); + expect(dockerfile).toContain('fc-cache -fv'); + expect(dockerfile).toContain('dbus-x11'); + }); + + it('verifies locale, fontconfig, XDG, process user, and container hiding evidence', () => { + const verify = readSource('ci/napcat-desktop-cn/verify.sh'); + expect(verify).toContain('locale -a'); + expect(verify).toContain('zh_CN.utf8'); + expect(verify).toContain('fc-match'); + expect(verify).toContain('/.dockerenv'); + expect(verify).toContain('/proc/1/cgroup'); + expect(verify).toContain('XDG_CONFIG_HOME=/app/.config'); + expect(verify).toContain('Asia/Shanghai'); + }); +});