feat: automate tencent private registry publishing

This commit is contained in:
Cheng Zhou
2026-03-30 20:15:06 +08:00
parent aa6cdd40e9
commit 956c47218e
7 changed files with 396 additions and 0 deletions
+8
View File
@@ -9,6 +9,14 @@
- [ ] `cd backend && python3 -m compileall app scripts`
- [ ] `cd frontend && npm run build`
## 1.1 腾讯云私有镜像校验
- [ ] `dev` 推送后,`<IP>:5000/ctms/ctms-backend``ctms-nginx``dev-latest` / `dev-<short_sha>` 标签已出现在私有仓库
- [ ] `release` 推送后,`<IP>:5000/ctms/ctms-backend``ctms-nginx``rc-release` / `rc-<short_sha>` 标签已出现在私有仓库
- [ ] `release/*` 推送后,`<IP>:5000/ctms/ctms-backend``ctms-nginx``rc-<release-branch>` / `rc-<short_sha>` 标签已出现在私有仓库
- [ ] `main` 推送后,`<IP>:5000/ctms/ctms-backend``ctms-nginx``latest` / `sha-<short_sha>` 标签已出现在私有仓库
- [ ] GitHub Actions 已成功 SSH 登录腾讯云服务器并执行远程构建脚本
- [ ] 部署机已执行 `docker login <IP>:5000`,且使用的是私有仓库 `htpasswd` 账号密码
## 2. 接口与权限回归
- [ ] ADMIN 账号可 `GET/PUT/PUBLISH/IMPORT-EXCEL/EXPORT-EXCEL`
- [ ] PM 账号可 `GET/PUT/PUBLISH/IMPORT-EXCEL/EXPORT-EXCEL`
@@ -0,0 +1,82 @@
# Tencent Cloud Private Registry Design
**Goal:** Add CI that automatically builds and pushes private `backend` and `nginx` images to a self-hosted Docker Registry running on a Tencent Cloud CVM, with `dev` publishing test tags, `release` and `release/*` publishing release-candidate tags, and `main` publishing formal tags.
**Decisions**
- Publish only two runtime images: `<registry-host>/ctms/ctms-backend` and `<registry-host>/ctms/ctms-nginx`.
- Keep the private registry on the Tencent Cloud CVM as a self-hosted `registry:2` instance protected by `htpasswd`.
- Trigger automation on pushes to `dev`, `release`, `release/*`, and `main`.
- Use GitHub Actions only as the orchestrator. Actual Docker build and push happen on the Tencent Cloud server over SSH.
- Keep `docker-compose.yaml` compatible with both local `build` workflows and private registry pulls.
**Approaches Considered**
- Recommended: GitHub Actions connects to the Tencent Cloud server over SSH and runs a server-local build-and-push script. This avoids GitHub-hosted runner limitations around insecure or self-signed private registries and keeps registry access local to the server.
- Alternative: GitHub Actions builds and pushes directly to `<IP>:5000`. This is simpler on paper but is fragile when the registry is exposed only as an IP endpoint and may use insecure or non-public TLS.
- Alternative: move first to a domain-backed HTTPS registry and then push directly from GitHub Actions. This is the clean long-term path but adds infrastructure work that is not required for the current goal.
**Architecture**
- A new GitHub Actions workflow triggers on pushes to `dev`, `release`, `release/*`, and `main`.
- The workflow authenticates to the Tencent Cloud server using SSH credentials stored in GitHub Secrets.
- The workflow syncs the repository contents to a fixed build directory such as `/opt/ctms-build/<repo>`.
- A server-local script logs in to the private registry, builds `backend` and `nginx`, applies branch-specific tags, and pushes the images to the registry.
**Registry Naming**
- Backend image: `<registry-host>/ctms/ctms-backend`
- Nginx image: `<registry-host>/ctms/ctms-nginx`
- `frontend` is intentionally not published because the current runtime topology already builds the frontend assets into the `nginx` image.
**Tagging Strategy**
- `dev` branch pushes publish:
- `<registry-host>/ctms/ctms-backend:dev-latest`
- `<registry-host>/ctms/ctms-backend:dev-<short_sha>`
- `<registry-host>/ctms/ctms-nginx:dev-latest`
- `<registry-host>/ctms/ctms-nginx:dev-<short_sha>`
- `release` branch pushes publish:
- `<registry-host>/ctms/ctms-backend:rc-release`
- `<registry-host>/ctms/ctms-backend:rc-<short_sha>`
- `<registry-host>/ctms/ctms-nginx:rc-release`
- `<registry-host>/ctms/ctms-nginx:rc-<short_sha>`
- `release/*` branch pushes publish:
- `<registry-host>/ctms/ctms-backend:rc-<release-branch>`
- `<registry-host>/ctms/ctms-backend:rc-<short_sha>`
- `<registry-host>/ctms/ctms-nginx:rc-<release-branch>`
- `<registry-host>/ctms/ctms-nginx:rc-<short_sha>`
- `main` branch pushes publish:
- `<registry-host>/ctms/ctms-backend:latest`
- `<registry-host>/ctms/ctms-backend:sha-<short_sha>`
- `<registry-host>/ctms/ctms-nginx:latest`
- `<registry-host>/ctms/ctms-nginx:sha-<short_sha>`
**Server Requirements**
- Docker installed on the Tencent Cloud server.
- A private `registry:2` instance listening on `<IP>:5000`.
- `htpasswd` authentication configured for the registry.
- SSH access from GitHub Actions to the server.
- A writable build directory such as `/opt/ctms-build`.
**GitHub Secrets**
- `TCLOUD_HOST`
- `TCLOUD_PORT`
- `TCLOUD_USER`
- `TCLOUD_SSH_KEY`
- `REGISTRY_HOST`
- `REGISTRY_USERNAME`
- `REGISTRY_PASSWORD`
**Compose Integration**
- `docker-compose.yaml` should define `image:` for `backend`, `backend-init`, and `nginx`, with defaults based on private registry variables such as `REGISTRY_HOST`.
- Existing `build:` blocks stay in place so local `docker compose up -d --build` continues to work.
- Deployment hosts can export `REGISTRY_HOST`, then run `docker login`, `docker compose pull`, `docker compose run --rm backend-init`, and `docker compose up -d`.
**Operational Notes**
- This design assumes the server-local script runs on the same machine that can log in to the private registry reliably.
- The GitHub workflow should not embed long shell logic inline; the repository should own a script under `scripts/` so the build logic stays versioned and testable.
- Direct verification of actual image publication depends on GitHub Actions reaching the Tencent Cloud server and cannot be proven locally without those secrets and network access.
**Verification**
- Push to `dev` and confirm both images appear with `dev-latest` and `dev-<short_sha>`.
- Push to `release` and confirm both images appear with `rc-release` and `rc-<short_sha>`.
- Push to `release/*` and confirm both images appear with `rc-<release-branch>` and `rc-<short_sha>`.
- Push to `main` and confirm both images appear with `latest` and `sha-<short_sha>`.
- Run `docker compose config` after compose changes and confirm the private registry defaults render correctly.
- Parse the workflow YAML successfully and inspect the remote build script for the expected tag logic and registry login behavior.
@@ -0,0 +1,146 @@
# Tencent Cloud Private Registry Implementation Plan
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
**Goal:** Add CI that triggers remote builds on a Tencent Cloud CVM and pushes private `backend` and `nginx` images into a self-hosted Docker Registry protected by `htpasswd`, for `dev`, `release`, `release/*`, and `main`.
**Architecture:** GitHub Actions runs on pushes to `dev`, `release`, `release/*`, and `main`, connects to the Tencent Cloud server over SSH, syncs the repository into a fixed build directory, and invokes a repository-owned shell script that logs in to the private registry, builds the images locally on the server, tags them according to branch, and pushes them.
**Tech Stack:** GitHub Actions, SSH, Docker, self-hosted `registry:2`, Docker Compose, FastAPI, Nginx
---
### Task 1: Replace GHCR Workflow with Tencent Registry Publish Workflow
**Files:**
- Modify: `.github/workflows/publish-images.yml`
**Step 1: Define push triggers and remote execution secrets**
Ensure the workflow triggers on pushes to `dev`, `release`, `release/*`, and `main`, and uses repository secrets for SSH host, port, user, SSH key, registry host, registry username, and registry password.
**Step 2: Sync repository content to the Tencent Cloud server**
Use an SSH-capable action or shell step to create the remote build directory and copy the current repository contents into `/opt/ctms-build/<repo>`.
**Step 3: Invoke the remote publish script**
Run the repository-owned remote script over SSH with environment values for:
- branch name
- commit SHA
- registry host
- registry credentials
**Step 4: Verify workflow structure**
Run: `ruby -e 'require "yaml"; YAML.load_file(".github/workflows/publish-images.yml")'`
Expected: PASS
### Task 2: Add Remote Build-And-Push Script
**Files:**
- Create: `scripts/build-and-push-registry.sh`
**Step 1: Implement branch-aware tag logic**
For `dev`, compute:
- `dev-latest`
- `dev-<short_sha>`
For `release`, compute:
- `rc-release`
- `rc-<short_sha>`
For `release/*`, compute:
- `rc-<release-branch>`
- `rc-<short_sha>`
For `main`, compute:
- `latest`
- `sha-<short_sha>`
Fail fast for unsupported branches.
**Step 2: Implement registry login and image builds**
Log in to `${REGISTRY_HOST}` using the supplied username and password, then build:
- `${REGISTRY_HOST}/ctms/ctms-backend`
- `${REGISTRY_HOST}/ctms/ctms-nginx`
**Step 3: Push both tags for both images**
Push every computed tag explicitly so the branch and immutable tags are both published.
**Step 4: Verify script syntax**
Run: `bash -n scripts/build-and-push-registry.sh`
Expected: PASS
### Task 3: Point Compose Defaults at the Private Registry
**Files:**
- Modify: `docker-compose.yaml`
**Step 1: Replace GHCR defaults with private registry defaults**
Set:
- `backend.image` to `${BACKEND_IMAGE:-${REGISTRY_HOST:-127.0.0.1:5000}/ctms/ctms-backend:latest}`
- `backend-init.image` to `${BACKEND_IMAGE:-${REGISTRY_HOST:-127.0.0.1:5000}/ctms/ctms-backend:latest}`
- `nginx.image` to `${NGINX_IMAGE:-${REGISTRY_HOST:-127.0.0.1:5000}/ctms/ctms-nginx:latest}`
Keep the current `build:` blocks intact.
**Step 2: Verify rendered compose**
Run: `docker compose config`
Expected: PASS with private registry image defaults rendered.
### Task 4: Update Deployment Documentation
**Files:**
- Modify: `README.md`
- Modify: `docs/guides/release-checklist.md`
**Step 1: Document the Tencent registry flow**
Explain that GitHub Actions triggers remote builds on the Tencent Cloud server and publishes to the private registry at `<IP>:5000`.
**Step 2: Document deployment commands**
Show that deployment hosts must run:
- `docker login <IP>:5000`
- `docker compose pull`
- `docker compose run --rm backend-init`
- `docker compose up -d`
**Step 3: Update release checklist**
Add checks for remote publish success on `dev`, `release`, `release/*`, and `main`, and for deployment-host registry authentication.
### Task 5: End-To-End Local Verification
**Files:**
- Verify only
**Step 1: Parse the workflow YAML**
Run: `ruby -e 'require "yaml"; YAML.load_file(".github/workflows/publish-images.yml")'`
Expected: PASS
**Step 2: Verify script syntax**
Run: `bash -n scripts/build-and-push-registry.sh`
Expected: PASS
**Step 3: Render compose**
Run: `docker compose config`
Expected: PASS
**Step 4: Inspect documentation**
Run: `sed -n '1,120p' README.md`
Expected: PASS with Tencent private registry deployment steps present.
Run: `sed -n '1,120p' docs/guides/release-checklist.md`
Expected: PASS with private registry release verification present.