kt-template-online-api/docs/superpowers/specs/2026-06-24-napcatqq-upstream-sync-runtime-release-pipeline-design.md

16 KiB

NapCatQQ Upstream Sync and Runtime Release Pipeline Design

Background

KT now carries a maintained NapCatQQ fork because QQ login, QR refresh, duplicate-login reset, and WebUI runtime state need source-level fixes. The production runtime image is a KT-derived Chinese desktop image:

kt-napcat-desktop-cn:<profile>

The current release loop still has a manual gap:

  1. Build the NapCatQQ fork locally.
  2. Stage the NapCat.Shell artifact with the API repository script.
  3. Copy or build the Docker context on the NAS.
  4. Verify the image.
  5. Update API runtime image/profile values.
  6. Push API/Admin and observe Jenkins/K8s.

That is too easy to drift. It also does not answer a bigger operational question: when upstream NapNeko/NapCatQQ ships a new latest release, which upstream changes can KT safely sync, and which changes conflict with KT's forked login/runtime fixes?

This design makes NapCatQQ its own release unit and adds a separate upstream release audit loop. The audit loop is read-only by default. It never merges upstream into KT automatically.

Primary upstream metadata sources:

  • GitHub latest release REST API: GET /repos/{owner}/{repo}/releases/latest.
  • GitHub compare REST API: GET /repos/{owner}/{repo}/compare/{basehead}.
  • Local Git history checks: git diff, git range-diff, git merge-tree, and file-level hot-zone scans.

Goals

  1. Create an independent NapCatQQ Jenkins pipeline for fork validation and runtime image release.
  2. Add a scheduled upstream latest-release audit that detects new upstream releases without automatically merging them.
  3. Classify upstream changes as safe candidate, manual-review required, or blocked.
  4. Produce auditable reports showing upstream deltas, KT fork patches, overlap files, hot-zone hits, and recommended action.
  5. Build verified kt-napcat-desktop-cn images from selected KT fork refs.
  6. Promote verified runtime images into API deployment through explicit parameters or promotion metadata, not ad hoc manifest edits.
  7. Keep production release completion tied to online smoke evidence, not Jenkins/K8s success alone.

Non-Goals

  • Do not bypass QQ/Tencent captcha, new-device verification, or account safety flows.
  • Do not auto-merge upstream release-latest into KT's maintained branch.
  • Do not push to the upstream NapNeko/NapCatQQ repository.
  • Do not treat OneBot heartbeat as QQ account login success.
  • Do not make the API repository own NapCat source patches.
  • Do not store GitHub tokens, Jenkins credentials, SSH keys, WebUI tokens, or Docker registry credentials in Git.
  • Do not automatically migrate existing production accounts to a new runtime image without explicit release confirmation.

Repositories and Ownership

D:\MyFiles\KT\GitHub\NapCatQQ

Owns KT's NapCat source fork and source-level tests.

Required remotes:

upstream = https://github.com/NapNeko/NapCatQQ.git
origin   = KT writable mirror or fork repository

The current local origin may point at upstream. The implementation must correct that before any Jenkins push path is enabled. Jenkins must refuse to push if origin resolves to NapNeko/NapCatQQ.

Recommended long-lived branches:

kt/runtime-maintenance
kt/sync/<upstream-release-tag>
kt/release/<runtime-profile>

D:\MyFiles\KT\Node\kt-template-online-api

Owns:

  • scripts/napcat-desktop-cn-stage-build.mjs
  • ci/napcat-desktop-cn/Dockerfile
  • ci/napcat-desktop-cn/verify.sh
  • API runtime image/profile parameters and deployment contract
  • API-side login/SSE safety guards

The API repository should not commit NapCat.Shell.zip artifacts.

Jenkins and NAS Docker

Own:

  • Scheduled upstream release audit execution.
  • NapCat fork build/test execution.
  • NAS-local Docker image build and verification.
  • Runtime promotion metadata and deployment observation artifacts.

Pipeline Overview

flowchart TD
  Upstream["NapNeko/NapCatQQ latest release"] --> Audit["KT-NapCatQQ-Upstream-Sync"]
  Fork["KT NapCatQQ fork"] --> Audit
  Audit --> Report["Audit report artifact"]
  Audit --> Candidate["Optional kt/sync/<tag> candidate branch"]
  Candidate --> Human["Human review and approval"]
  Fork --> Release["KT-NapCatQQ-Runtime-Release"]
  Human --> Release
  Release --> Image["kt-napcat-desktop-cn:<profile>"]
  Image --> ApiDeploy["API Jenkins deploy with runtime image/profile params"]
  ApiDeploy --> Observe["deploy-observation + online smoke"]

Two Jenkins jobs are required:

KT-NapCatQQ-Upstream-Sync
KT-NapCatQQ-Runtime-Release

The upstream sync job is scheduled and read-only by default. The runtime release job is manually triggered, or triggered by an approved candidate branch.

Upstream Sync Audit Job

Trigger

  • Scheduled, for example once per day.
  • Manual trigger with UPSTREAM_RELEASE_TAG override.

Inputs

UPSTREAM_REPO=NapNeko/NapCatQQ
FORK_BRANCH=kt/runtime-maintenance
LAST_ACCEPTED_UPSTREAM_BASE=<commit recorded from previous release marker>
UPSTREAM_RELEASE_TAG=<optional manual override>
CREATE_CANDIDATE_BRANCH=false by default

Steps

  1. Fetch upstream metadata.

    • If UPSTREAM_RELEASE_TAG is empty, call GitHub latest release API.
    • Resolve the release tag to a peeled commit with git ls-remote --tags upstream <tag>^{} or equivalent.
    • Record release name, tag, commit, published time, and release URL.
  2. Fetch fork and upstream history.

    • Fetch upstream.
    • Fetch KT writable origin.
    • Checkout FORK_BRANCH.
    • Confirm working tree is clean.
  3. Compute upstream delta.

    • upstreamDelta = LAST_ACCEPTED_UPSTREAM_BASE..UPSTREAM_RELEASE_COMMIT
    • Capture commits, changed files, rename/delete status, package lock changes, and hot-zone hits.
  4. Compute KT fork patch set.

    • forkPatch = LAST_ACCEPTED_UPSTREAM_BASE..FORK_BRANCH
    • Capture KT-only commits and files.
  5. Detect overlap and risk.

    • overlapFiles = upstreamDelta.files intersect forkPatch.files
    • hotZoneFiles = upstreamDelta.files matching login/runtime/build patterns
    • Run git merge-tree or an equivalent dry merge against the release commit.
    • Run git range-diff when a candidate rebase can be generated.
  6. Classify the release.

    • safe-candidate: no hot-zone hit, no overlap with KT patch files, lockfile/build changes pass static checks.
    • manual-review: hot-zone touched, overlap touched, package/build graph changed, or range-diff is non-trivial.
    • blocked: dry merge conflicts, tests cannot install/build, artifact structure changed, or required upstream metadata cannot be verified.
  7. Write artifacts.

    • Markdown human report.
    • JSON machine report.
    • File lists for upstream delta, fork patch, overlap, and hot zones.
    • Suggested next action.
  8. Optionally create candidate branch.

    • Only allowed when classification is safe-candidate or manually requested.
    • Branch name: kt/sync/<release-tag>.
    • Candidate creation applies KT patches on top of upstream release without merging back to FORK_BRANCH.
    • Candidate branch must be pushed only to KT writable remote.
    • Candidate branch must never auto-merge.

Hot Zones

The audit treats these as high-risk areas:

packages/napcat-core/**/login*
packages/napcat-core/**/qrcode*
packages/napcat-shell/**
packages/napcat-framework/**
packages/napcat-webui-backend/**/QQLogin*
packages/napcat-webui-backend/**/Data*
packages/napcat-webui-backend/**/auth*
packages/napcat-webui-frontend/**
packages/napcat-adapter/**
packages/napcat-onebot/**
packages/napcat-vite/**
package.json
pnpm-lock.yaml
tsconfig*.json
vite*.ts

This list is intentionally conservative. If upstream changes login state, QR generation, WebUI auth, OneBot startup, or build packaging, the sync must go through human review.

Audit Report Contract

JSON artifact:

{
  "upstream": {
    "repo": "NapNeko/NapCatQQ",
    "releaseTag": "v0.0.0",
    "releaseCommit": "0000000000000000000000000000000000000000",
    "publishedAt": "2026-06-24T00:00:00Z",
    "releaseUrl": "https://github.com/NapNeko/NapCatQQ/releases/tag/v0.0.0"
  },
  "fork": {
    "branch": "kt/runtime-maintenance",
    "headCommit": "0000000000000000000000000000000000000000",
    "lastAcceptedUpstreamBase": "0000000000000000000000000000000000000000"
  },
  "classification": "manual-review",
  "reasonCodes": ["HOT_ZONE_CHANGED", "FORK_PATCH_OVERLAP"],
  "upstreamChangedFiles": [],
  "forkPatchFiles": [],
  "overlapFiles": [],
  "hotZoneFiles": [],
  "candidateBranch": null,
  "recommendedAction": "Review hot-zone changes before creating a candidate branch."
}

The report must be safe to archive and share. It must not include tokens, secrets, private env files, QQ passwords, captcha tickets, or WebUI credentials.

Runtime Release Job

Trigger

  • Manual trigger with an approved source ref.
  • Optional upstream-sync trigger after a candidate branch is reviewed and approved.

Inputs

NAPCAT_SOURCE_REF=kt/runtime-maintenance or kt/sync/<tag>
UPSTREAM_RELEASE_TAG=<tag recorded in audit>
UPSTREAM_RELEASE_COMMIT=<commit recorded in audit>
RUNTIME_PROFILE=desktop-cn-vN
NAPCAT_BASE_IMAGE=mlikiowa/napcat-docker@sha256:<digest>
API_REF=main
PROMOTE_TO_API=false by default
CANARY_ACCOUNT_ID=<optional>

NAPCAT_BASE_IMAGE must resolve to a digest before Docker build. If the user chooses to base on mlikiowa/napcat-docker:latest, the pipeline must first pull it, resolve its RepoDigest, and use the digest in the actual Docker build and release marker.

Steps

  1. Checkout NapCatQQ.

    • Use KT writable fork remote.
    • Checkout NAPCAT_SOURCE_REF.
    • Confirm clean tree.
    • Record fork commit.
  2. Install and verify source.

    • pnpm install --frozen-lockfile
    • Focused login/runtime tests.
    • pnpm run typecheck
    • pnpm run build:webui
    • pnpm run build:shell
    • pnpm run build:framework
  3. Checkout API repository as a build integration dependency.

    • Use API_REF.
    • Run the stage-build script with --napcat-root.
    • Ensure the staged fork-artifact.json contains:
      • upstream release tag
      • upstream release commit
      • last accepted upstream base
      • fork commit
      • dist sha256
      • napcat.mjs sha256
      • base image digest
      • Jenkins build URL
  4. Build NAS-local Docker image.

    • Build from staged context.

    • Tag immutable image:

      kt-napcat-desktop-cn:<upstream-tag>-kt.<jenkins-build>
      
    • Tag promotion alias only after verify:

      kt-napcat-desktop-cn:<runtime-profile>
      
  5. Verify image.

    • Run a temporary container.
    • Execute /ci/napcat-desktop-cn/verify.sh.
    • Verify locale, timezone, fonts, XDG paths, hidden Docker markers, fork marker, artifact hash, and critical runtime symbols.
    • Remove temporary container.
    • Inspect image ID and digest-like local image ID.
  6. Archive release metadata.

    • napcat-runtime-release.json
    • Docker image inspect output.
    • fork-artifact.json
    • test summaries.
  7. Optional API promotion.

    • If PROMOTE_TO_API=true, trigger API Jenkins with runtime image/profile parameters.
    • API deploy must update K8s runtime env through a controlled deployment parameter or generated manifest overlay.
    • API deploy must not require hand-editing k8s/prod/api.yaml for every runtime image.
  8. Deployment observation and smoke.

    • Run API deploy-observation.
    • Verify API /health/runtime.
    • Verify K8s deployment generation, pod image, ready replicas, restart count, and logs.
    • For QQ login behavior, complete only after a real account smoke or a clearly documented manual-scan wait state.

API Promotion Contract

The API Jenkinsfile should gain optional parameters:

QQBOT_NAPCAT_IMAGE_OVERRIDE=
QQBOT_NAPCAT_DESKTOP_PROFILE_VERSION_OVERRIDE=

When set, the K8s deploy stage must apply these as runtime env values for the API deployment. The implementation may use a generated manifest overlay or kubectl set env, but it must leave secrets out of Git and record the effective values in deployment evidence.

API tests must enforce:

  • Production no longer depends on latest.
  • The runtime image override path is explicit.
  • The default profile value is still a known safe fallback.
  • The API code does not silently downgrade to older runtime profiles.

Data Flow

sequenceDiagram
  participant Upstream as GitHub Upstream
  participant Sync as Upstream Sync Jenkins
  participant Fork as KT NapCatQQ Fork
  participant Release as Runtime Release Jenkins
  participant ApiRepo as API Repo
  participant Docker as NAS Docker
  participant ApiDeploy as API Jenkins

  Sync->>Upstream: read latest release metadata
  Sync->>Fork: fetch maintained branch
  Sync->>Sync: diff upstream delta vs KT fork patch
  Sync-->>Fork: optional kt/sync/<tag> branch, never auto-merge
  Sync-->>Sync: archive audit report
  Release->>Fork: checkout approved source ref
  Release->>Release: test, typecheck, build webui/shell/framework
  Release->>ApiRepo: run stage-build script
  Release->>Docker: build and verify kt-napcat-desktop-cn image
  Release->>ApiDeploy: optional promote with image/profile params
  ApiDeploy-->>Release: rollout and smoke evidence

Error Handling

  • GitHub API rate limit or outage: mark audit as blocked with retry advice; do not infer latest release from stale data unless explicitly allowed.
  • Upstream release has no resolvable tag commit: mark blocked.
  • Fork writable remote points to upstream: fail before push.
  • Dirty workspace: fail before audit candidate or release.
  • Hot-zone overlap: mark manual-review; do not create or merge a candidate unless explicitly requested.
  • Dry merge conflict: mark blocked.
  • pnpm install, tests, typecheck, shell/framework build failure: mark runtime release failed; do not build or promote an image.
  • Docker base image cannot resolve to digest: fail before build.
  • verify.sh fails: remove verify container, keep artifacts, do not tag promotion alias.
  • API promotion deploy succeeds but online smoke fails: keep deployment evidence separate from functional completion and provide rollback steps.

Rollback

Runtime rollback is controlled by the API runtime image/profile values:

  1. Identify the last verified runtime image/profile from release artifacts.
  2. Trigger API Jenkins with previous QQBOT_NAPCAT_IMAGE_OVERRIDE and profile.
  3. Observe K8s rollout.
  4. Existing online NapCat containers are not automatically rebuilt. Account-level migration remains explicit because container rebuilds affect QQ device/login risk.

Validation Strategy

Upstream Sync Job

Local/job validation:

pnpm --dir mcp/ktWorkflow run self-test
git diff --check

Jenkins dry run must show:

  • Latest release metadata resolved.
  • Last accepted upstream base resolved.
  • Upstream delta file list.
  • Fork patch file list.
  • Overlap/hot-zone classification.
  • Report artifact paths.

Runtime Release Job

NapCatQQ:

corepack pnpm install --frozen-lockfile
corepack pnpm --filter napcat-test run test -- loginQrcodeRefresh webuiLoginSourceWiring webuiQQLoginHandlers webuiLoginRuntime
corepack pnpm run typecheck
corepack pnpm run build:webui
corepack pnpm run build:shell
corepack pnpm run build:framework

API integration:

corepack pnpm exec jest test/modules/qqbot/napcat/napcat-desktop-cn-image.spec.ts test/modules/qqbot/napcat/runtime-protocol-profile.spec.ts --runTestsByPath --runInBand
corepack pnpm run typecheck
git diff --check

NAS image:

docker build --build-arg NAPCAT_BASE_IMAGE="$NAPCAT_BASE_IMAGE_DIGEST" -t "$IMMUTABLE_TAG" -f "$STAGED_CONTEXT/ci/napcat-desktop-cn/Dockerfile" "$STAGED_CONTEXT"
docker run -d --name "$VERIFY_CONTAINER" "$IMMUTABLE_TAG"
docker exec "$VERIFY_CONTAINER" sh /ci/napcat-desktop-cn/verify.sh
docker rm -f "$VERIFY_CONTAINER"
docker tag "$IMMUTABLE_TAG" "$PROMOTION_TAG"

Online:

  • API deploy-observation passes.
  • API /health/runtime passes.
  • For login-runtime releases, a canary account either logs in successfully or reaches a clear captcha/new-device/manual-scan pending state with a fresh QR and correct SSE/Admin status.

Completion Criteria

  • NapCatQQ has a standalone Jenkins release path.
  • A scheduled audit detects upstream latest releases and writes safe reports.
  • Upstream sync never auto-merges into KT maintenance branches.
  • Hot-zone conflicts are blocked or marked for manual review.
  • Runtime images are built from approved fork refs and verified inside containers.
  • API deployment consumes runtime image/profile through an explicit promotion contract.
  • Jenkins/K8s deployment evidence and online QQBot/NapCat smoke evidence are both captured before claiming a release complete.