Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 14 additions & 39 deletions .github/workflows/deploy-tencent.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,8 @@ env:

jobs:
build:
name: Build Web image
name: Validate deployment image
runs-on: ubuntu-latest
environment: tencent
steps:
- name: Checkout
uses: actions/checkout@v4
Expand All @@ -40,47 +39,27 @@ jobs:
uses: docker/setup-buildx-action@v3

- name: Build image
if: github.event_name == 'pull_request'
uses: docker/build-push-action@v6
with:
context: apps/web
file: apps/web/Dockerfile
platforms: linux/amd64
outputs: type=docker,dest=${{ runner.temp }}/meteortest-image.tar
tags: ${{ env.IMAGE_NAME }}:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max

- name: Compress image artifact
if: github.event_name != 'pull_request'
run: gzip -1 < "${RUNNER_TEMP}/meteortest-image.tar" > deploy/meteortest-image.tar.gz

- name: Upload image artifact to Tencent
if: github.event_name != 'pull_request'
env:
DEPLOY_KEY: ${{ secrets.TENCENT_ARTIFACT_SSH_KEY }}
DEPLOY_KNOWN_HOSTS: ${{ secrets.TENCENT_ARTIFACT_KNOWN_HOSTS }}
DEPLOY_HOST: ${{ vars.TENCENT_ARTIFACT_HOST }}
DEPLOY_USER: ${{ vars.TENCENT_ARTIFACT_USER }}
run: |
key_file="${RUNNER_TEMP}/artifact-upload-key"
known_hosts_file="${RUNNER_TEMP}/artifact-known-hosts"
printf '%s\n' "${DEPLOY_KEY}" > "${key_file}"
printf '%s\n' "${DEPLOY_KNOWN_HOSTS}" > "${known_hosts_file}"
chmod 0600 "${key_file}" "${known_hosts_file}"
ssh -i "${key_file}" -o IdentitiesOnly=yes -o StrictHostKeyChecking=yes \
-o UserKnownHostsFile="${known_hosts_file}" \
"${DEPLOY_USER}@${DEPLOY_HOST}" "${GITHUB_SHA}" \
< deploy/meteortest-image.tar.gz
rm -f deploy/meteortest-image.tar.gz "${key_file}" "${known_hosts_file}"

- name: Upload deployment manifest
- name: Upload validated source artifact
if: github.event_name != 'pull_request'
uses: actions/upload-artifact@v4
with:
name: meteortest-deployment-${{ github.sha }}
name: meteortest-source-${{ github.sha }}
path: |
apps/web
deploy/docker-compose.yml
deploy/deploy-container.sh
!apps/web/node_modules
!apps/web/.next
retention-days: 7

deploy:
Expand All @@ -90,11 +69,11 @@ jobs:
runs-on: [self-hosted, linux, x64, tencent, meteortest]
environment: tencent
steps:
- name: Download deployment manifest
- name: Download validated source artifact
uses: actions/download-artifact@v4
with:
name: meteortest-deployment-${{ github.sha }}
path: deployment
name: meteortest-source-${{ github.sha }}
path: source

- name: Resolve target
id: target
Expand All @@ -114,8 +93,8 @@ jobs:
echo "public_url=https://mt-pre.jcmeteor.com/" >> "$GITHUB_OUTPUT"
fi

- name: Load image artifact
run: gzip -dc "/srv/deploy-inbox/meteortest/${GITHUB_SHA}.tar.gz" | docker load
- name: Build image from artifact
run: docker build --tag "meteortest-web:${GITHUB_SHA}" --file source/apps/web/Dockerfile source/apps/web

- name: Deploy
env:
Expand All @@ -128,9 +107,5 @@ jobs:
RUNTIME_ENV_FILE: /etc/meteortest/meteortest-web.env
SHADOW_PORT: ${{ steps.target.outputs.shadow_port }}
run: |
chmod +x deployment/deploy-container.sh
deployment/deploy-container.sh

- name: Remove uploaded image artifact
if: success()
run: rm -f "/srv/deploy-inbox/meteortest/${GITHUB_SHA}.tar.gz"
chmod +x source/deploy/deploy-container.sh
source/deploy/deploy-container.sh
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ main -> mt-pre.jcmeteor.com
release -> meteortest.jcmeteor.com
```

The detailed Docker image artifact architecture, runner, branch, environment, port mapping, PM2 migration, and rollback flow lives in `docs/tencent-docker-deployment.md`.
The detailed Docker/source artifact architecture, runner, branch, environment, port mapping, PM2 migration, and rollback flow lives in `docs/tencent-docker-deployment.md`.

Production publishing is automated by the GitHub Actions `Release Manager` workflow:

Expand Down
27 changes: 0 additions & 27 deletions deploy/receive-image-upload.sh

This file was deleted.

2 changes: 1 addition & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ This is the single entry point for MeteorTest documentation. Start here for new
| Supabase runbook | `supabase-account-data-runbook.md` / `supabase-account-data-runbook.zh-CN.md` | Auth/RLS, preferences, AI history, display refs SQL execution and verification. |
| Local Agent operations | `local-agent-operations.md` / `local-agent-operations.zh-CN.md` | Agent daemon, check interval, heartbeat, logs, OpenClaw checks. |
| Public preview deployment | `vercel-public-preview.md` / `vercel-public-preview.zh-CN.md` | Vercel public preview deployment and safety checks. |
| Tencent Docker deployment | `tencent-docker-deployment.md` / `tencent-docker-deployment.zh-CN.md` | Docker image artifact architecture, main/release mapping, PM2 migration, and rollback. |
| Tencent Docker deployment | `tencent-docker-deployment.md` / `tencent-docker-deployment.zh-CN.md` | Docker/source artifact architecture, main/release mapping, PM2 migration, and rollback. |
| Release automation | `release-manager.md` | GitHub Actions release workflow, release PR automation, and recovery commands. |
| Private Agent loop | `private-agent-preview-loop.md` / `private-agent-preview-loop.zh-CN.md` | Validation flow for public Web plus private Agent execution. |
| Data exposure boundary | `internal-id-exposure-hardening.md` / `internal-id-exposure-hardening.zh-CN.md` | Internal UUIDs, public refs, DTO/View Model rules. |
Expand Down
2 changes: 1 addition & 1 deletion docs/README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
| Supabase 手册 | `supabase-account-data-runbook.zh-CN.md` / `supabase-account-data-runbook.md` | Auth/RLS、账号偏好、AI 历史、display refs 的 SQL 执行与验证。 |
| Local Agent 运维 | `local-agent-operations.zh-CN.md` / `local-agent-operations.md` | Agent 常驻、检查频率、心跳、日志、OpenClaw 巡检。 |
| 公网预览部署 | `vercel-public-preview.zh-CN.md` / `vercel-public-preview.md` | Vercel 公网预览部署和安全检查。 |
| 腾讯云 Docker 部署 | `tencent-docker-deployment.zh-CN.md` / `tencent-docker-deployment.md` | Docker 镜像制品架构、main/release 映射、PM2 迁移和回滚。 |
| 腾讯云 Docker 部署 | `tencent-docker-deployment.zh-CN.md` / `tencent-docker-deployment.md` | Docker + 源码 Artifact 架构、main/release 映射、PM2 迁移和回滚。 |
| 发布自动化 | `release-manager.md` | GitHub Actions 发布入口、release PR 自动化和中断恢复命令。 |
| 私有 Agent 闭环 | `private-agent-preview-loop.zh-CN.md` / `private-agent-preview-loop.md` | 私有 Agent 连接公网 Web 后端的验证流程。 |
| 数据暴露边界 | `internal-id-exposure-hardening.zh-CN.md` / `internal-id-exposure-hardening.md` | 内部 UUID、公开引用、DTO/View Model 规则。 |
Expand Down
8 changes: 4 additions & 4 deletions docs/tencent-docker-deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ Nginx MUST continue binding public ports 80/443. Containers MUST publish only to

1. A GitHub-hosted runner checks out the requested commit.
2. CI installs dependencies in `apps/web`, then runs lint and the production build. Repository-wide validation continues to cover the Python Agent separately.
3. CI exports the multi-stage Next.js standalone image as a compressed Docker image artifact.
3. CI validates the Docker build on pull requests and uploads compact source as a GitHub Actions artifact after merge.
4. The image is tagged with an immutable commit SHA. Branch and release tags MAY be aliases, but deployment MUST resolve to the SHA tag.
5. The MeteorTest Tencent runner loads the uploaded artifact into Docker and updates only the matching Compose project.
5. The MeteorTest Tencent runner builds from the artifact with the server-side Docker layer cache and updates only the matching Compose project.
6. The runner waits for container health and verifies the public domain.
7. A failed health check MUST restore the previous image SHA.

Expand All @@ -46,7 +46,7 @@ Docker migration covers only `apps/web`. The private Python Local Agent MUST rem

## Configuration and secrets

Real Web credentials remain in `/etc/meteortest/meteortest-web.env`. Compose injects the file at container startup. The GitHub-hosted runner sends the compressed image directly to a Tencent inbox through an SSH key restricted to that upload command. The self-hosted runner only loads and deploys it. No container-registry password or interactive upload shell is required. Supabase service-role, AI provider, Agent, and project execution secrets MUST NOT enter the image artifact.
Real Web credentials remain in `/etc/meteortest/meteortest-web.env`. Compose injects the file at container startup. The self-hosted runner downloads the validated source artifact, builds with the server-side Docker layer cache, and deploys it. It does not pull the Git repository and requires no container-registry password. Supabase service-role, AI provider, Agent, and project execution secrets MUST NOT enter the source artifact or image.

## Compose requirements

Expand Down Expand Up @@ -79,7 +79,7 @@ Do not run `pm2 kill`. Keep PM2 definitions and source directories until both en

1. resolve the immutable image SHA;
2. record the currently running SHA;
3. download and load the image artifact;
3. download the source artifact and build the image with Docker layer cache;
4. update the matching Compose project from the local immutable image;
5. wait for container health;
6. verify the localhost port and public domain;
Expand Down
6 changes: 3 additions & 3 deletions docs/tencent-docker-deployment.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Nginx MUST 继续监听公网 80/443 端口。容器 MUST 只发布到 `127.0.0.

1. GitHub 托管 Runner 检出目标提交。
2. CI 在 `apps/web` 安装依赖并执行 lint 和生产构建;仓库级验证继续单独覆盖 Python Agent。
3. CI 将多阶段 Next.js standalone 镜像导出为压缩的 Docker 镜像制品
3. CI 在 PR 中验证 Docker 构建;合并后将精简源码作为 GitHub Actions Artifact 上传
4. 镜像使用不可变 commit SHA 标签;分支和版本标签 MAY 作为别名,但部署 MUST 最终解析到 SHA 标签。
5. MeteorTest 专属腾讯 Runner 下载 Artifact、将不可变镜像加载到 Docker,并只更新对应 Compose 项目。
6. Runner 等待容器健康并验证公网域名。
Expand Down Expand Up @@ -46,7 +46,7 @@ Nginx MUST 继续监听公网 80/443 端口。容器 MUST 只发布到 `127.0.0.

## 配置与密钥

真实 Web 凭据继续保存在 `/etc/meteortest/meteortest-web.env`,由 Compose 在容器启动时注入。GitHub 托管 Runner 使用只允许写入指定目录的 SSH 密钥,将压缩镜像直传到腾讯云制品收件箱;自托管 Runner 只负责加载和部署。该通道不需要镜像仓库密码,上传账号也不能获得交互式 Shell。Supabase service-role、AI provider、Agent 和项目执行密钥 MUST NOT 进入镜像制品
真实 Web 凭据继续保存在 `/etc/meteortest/meteortest-web.env`,由 Compose 在容器启动时注入。自托管 Runner 下载经验证的源码 Artifact,利用服务器 Docker 层缓存构建并部署,不拉取 Git 仓库,也不需要镜像仓库密码。Supabase service-role、AI provider、Agent 和项目执行密钥 MUST NOT 进入源码 Artifact 或镜像

## Compose 要求

Expand Down Expand Up @@ -79,7 +79,7 @@ Nginx MUST 继续监听公网 80/443 端口。容器 MUST 只发布到 `127.0.0.

1. 解析新的不可变镜像 SHA;
2. 记录当前运行 SHA;
3. 下载并加载镜像 Artifact;
3. 下载源码 Artifact,并利用 Docker 层缓存构建镜像
4. 使用本地不可变镜像更新对应 Compose 项目;
5. 等待容器健康;
6. 验证 localhost 端口和公网域名;
Expand Down
Loading