From d6e8ce848c99c5ec6c9d15487e0bbe8a8ca4f058 Mon Sep 17 00:00:00 2001 From: sunlei Date: Thu, 25 Jun 2026 02:57:36 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E5=AF=B9=E9=BD=90NapCat=E8=BF=90?= =?UTF-8?q?=E8=A1=8C=E6=97=B6=E6=9E=84=E5=BB=BA=E5=85=83=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E6=8C=87=E5=8D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ci/napcat-desktop-cn/README.md | 30 +++++++++++++++---- .../napcat/napcat-desktop-cn-image.spec.ts | 15 ++++++++++ 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/ci/napcat-desktop-cn/README.md b/ci/napcat-desktop-cn/README.md index d2ec27e..52e15cb 100644 --- a/ci/napcat-desktop-cn/README.md +++ b/ci/napcat-desktop-cn/README.md @@ -10,29 +10,47 @@ corepack pnpm --dir D:\MyFiles\KT\GitHub\NapCatQQ --filter napcat-webui-frontend corepack pnpm --dir D:\MyFiles\KT\GitHub\NapCatQQ run build:shell ``` +Resolve release evidence before staging. Production and release builds must use an immutable upstream base image digest, not an unpinned tag: + +```powershell +docker pull mlikiowa/napcat-docker:latest +$napcatBaseImageDigest = docker image inspect mlikiowa/napcat-docker:latest --format '{{index .RepoDigests 0}}' +if (-not $napcatBaseImageDigest -or $napcatBaseImageDigest -notmatch '@sha256:') { + throw 'NapCat upstream image digest not found; release builds must use repo@sha256:... evidence.' +} + +$upstreamReleaseTag = 'v4.8.100' +$upstreamReleaseCommit = '0123456789abcdef0123456789abcdef01234567' +$jenkinsBuildUrl = 'https://jenkins.example/job/NapCatQQ/123/' +``` + Stage Docker build context: ```powershell node scripts/napcat-desktop-cn-stage-build.mjs ` --napcat-root D:\MyFiles\KT\GitHub\NapCatQQ ` - --out .kt-workspace\napcat-desktop-cn-build + --out .kt-workspace\napcat-desktop-cn-build ` + --upstream-release-tag $upstreamReleaseTag ` + --upstream-release-commit $upstreamReleaseCommit ` + --napcat-base-image-digest $napcatBaseImageDigest ` + --jenkins-build-url $jenkinsBuildUrl ``` +The staged context must contain `NapCat.Shell` and `ci/napcat-desktop-cn/fork-artifact.json`. The API repo does not commit `NapCat.Shell.zip`; it is rebuilt from the staged `NapCat.Shell` directory inside the Docker image. `fork-artifact.json` must carry complete marker metadata for the fork commit, upstream base commit, upstream release tag, upstream release commit, Jenkins build URL, `napcatMjsSha256`, dist SHA256, and `napcatBaseImageDigest`. + Build and verify: ```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 ` + --build-arg NAPCAT_BASE_IMAGE=$napcatBaseImageDigest ` -t kt-napcat-desktop-cn:desktop-cn-v8 ` -f .kt-workspace/napcat-desktop-cn-build/ci/napcat-desktop-cn/Dockerfile ` .kt-workspace/napcat-desktop-cn-build -$name = "kt-napcat-v6-verify-$([DateTimeOffset]::UtcNow.ToUnixTimeSeconds())" +$name = "kt-napcat-v8-verify-$([DateTimeOffset]::UtcNow.ToUnixTimeSeconds())" docker run -d --name $name kt-napcat-desktop-cn:desktop-cn-v8 docker exec $name sh /ci/napcat-desktop-cn/verify.sh docker rm -f $name ``` -Record the final image digest in `QQBOT_NAPCAT_IMAGE`. +Record the final image digest in `QQBOT_NAPCAT_IMAGE`, and keep the matching `fork-artifact.json` with the release evidence. For local Windows rehearsal, placeholder `$upstreamReleaseTag`, `$upstreamReleaseCommit`, and `$jenkinsBuildUrl` values are acceptable only if the image is not promoted. diff --git a/test/modules/qqbot/napcat/napcat-desktop-cn-image.spec.ts b/test/modules/qqbot/napcat/napcat-desktop-cn-image.spec.ts index 943ac01..f40fd0c 100644 --- a/test/modules/qqbot/napcat/napcat-desktop-cn-image.spec.ts +++ b/test/modules/qqbot/napcat/napcat-desktop-cn-image.spec.ts @@ -63,6 +63,21 @@ describe('NapCat Chinese Desktop Runtime image assets', () => { expect(script).toContain('Refusing to delete unsafe output root'); }); + /** + * Verifies the checked-in operator guide documents the full release evidence contract. + */ + it('documents complete release metadata for staging NapCat Shell artifacts', () => { + const readme = readSource('ci/napcat-desktop-cn/README.md'); + + expect(readme).toContain('--upstream-release-tag'); + expect(readme).toContain('--upstream-release-commit'); + expect(readme).toContain('--napcat-base-image-digest'); + expect(readme).toContain('--jenkins-build-url'); + expect(readme).toContain('NapCat.Shell.zip'); + expect(readme).toContain('fork-artifact.json'); + expect(readme).toContain('sha256:'); + }); + it('uses source-built NapCat Shell artifact instead of bundled JS patching', () => { const dockerfile = readSource('ci/napcat-desktop-cn/Dockerfile'); const verify = readSource('ci/napcat-desktop-cn/verify.sh');