Skip to content

chore(deploy): 收口 legacy compose/脚本并同步 cd-production 引用 (#1527 PR2) - #1590

Merged
DeliciousBuding merged 1 commit into
masterfrom
chore/deploy-pr2
Aug 3, 2026
Merged

chore(deploy): 收口 legacy compose/脚本并同步 cd-production 引用 (#1527 PR2)#1590
DeliciousBuding merged 1 commit into
masterfrom
chore/deploy-pr2

Conversation

@DeliciousBuding

@DeliciousBuding DeliciousBuding commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

背景

#1527 PR1(cfde8494)确立 deployments/production/docker-compose.yml 为唯一权威 production compose,并挂 verify-deployment-shape.ps1 门禁(遗留清单注册制 + "新增第二份手维护 production compose 必 FAIL"机器证明)。本 PR(PR2)完成 legacy compose/脚本收口与 cd-production.yml 引用同步。

Compose normalized 差异表(docker compose v5.3.1 config --format json,本机可用)

对比对象:权威 deployments/production/docker-compose.yml vs legacy 三份(docker-compose.prod.yml / docker-compose.us1.yml / hk2/docker-compose.hk2.yml)。

维度 权威 legacy ×3
services hub-server, redis hub-server, redis, postgres(独立 PG 16)
hub-server image agenthub-hub-server:latest(SSOT) 同(默认值)
hub-server mem / depends_on 384m / 仅 redis 256m / postgres+redis
hub-server healthcheck 30s/30s 15s/15s
hub-server DB env ${PG_HOST}:5433 + sslmode=require(host/Azure PG 直连) postgres:5432(compose 内 PG)
hub-server redis 密码 空(本地轻量 redis) 必填强密码
hub-server 额外 env AGENTHUB_ENV/PPROF_USER/PASS/CORS/S3×6/EDGE×2/JWKS_URI/loopback redirects
hub-server UPLOAD_DIR /app/uploads ./uploads
hub-server pull_policy/dns never / 8.8.8.8,1.1.1.1
redis 资源/端口 128m, 0.3c, 64 pids, 127.0.0.1:6380:6379 384m, 0.5c, 128 pids, 仅 expose
redis healthcheck/logging 10s / 5m×2 5s / 10m×3
volumes redis_data, uploads_data + agenthub_pg_data
networks agenthub-net (bridge) 相同

结论:legacy 三份是同一套废弃的"独立 PG+Redis"拓扑(三份之间仅 CORS 列表、ALLOWED_REDIRECT_URIS loopback、redis healthcheck 微差),与权威模板(host/Azure PG 直连 + 轻量本地 redis)是拓扑级差异,不是 region 变体。server SSOT(projects/agenthub/STATE.md)确认 live 仅 hk3、us1 仅冷备、hk2 无记录。因此直接删除,不建 override:override 会复活废弃拓扑,且会触发 verify-deployment-shape"第二份手维护 production compose 必 FAIL"负向用例。

最终形态

删除(14 个文件 / hk2 目录整体)

  • hub-server/deployments/docker-compose.prod.ymldocker-compose.us1.ymlhk2/docker-compose.hk2.yml
  • hub-server/deployments/deploy.shhk2/deploy-hk2.shhk2/deploy-web-hk2.sh(纯人工运维胶水,运维由 server SSOT 覆盖)
  • hub-server/deployments/CaddyfileCaddyfile.prod.env.production.examplebackup-cron.dockerignore(构建上下文为仓库根)
  • hk2/.env.examplehk2/nginx-hk2-v2.confhk2/nginx-hk2.conf

保留

  • hub-server/deployments/Dockerfile(构建输入,cd-hub-server/cd-production 消费,未改动)
  • hub-server/deployments/docker-entrypoint.sh(构建输入,Dockerfile COPY 依赖,未改动)
  • hub-server/deployments/README.md(精简为构建输入说明;verify-doc-ssot 要求该文件存在)
  • root docker-compose.yml(local-development shape,任务书明确不删)

无新增 override 文件。

引用变更清单

文件 变更
scripts/verify/verify-deployment-shape.ps1 遗留清单注册制 → 关闭态:hub-server/deployments/ 下出现任何 compose 即 FAIL
scripts/verify/tests/verify-deployment-shape.Tests.ps1 fixture 不再拷贝 legacy;负向用例 2 改为"legacy compose 复活必 FAIL";正例 + 4 负例共 5/5
.github/workflows/cd-pr-check.yml 移除 deploy.sh / .env.production.example 检查与 deploy.sh 结构校验 step;保留 Dockerfile + 权威 compose 检查
.github/workflows/cd-production.yml env 区声明、staging/production 部署指引回显、回滚指引(Option B/C/D)、health-check 清单全部改指 deployments/production/docker-compose.yml(仅引用同步,未动行为/权限/secrets)
scripts/release/verify-web-deploy-readiness.ps1 6 条生产 OIDC 断言从 legacy 文件改指权威 compose + 权威 .env.example(env 模板补 OIDC 回调/交换端点/loopback 说明段,语义对齐权威 compose:ALLOWED_REDIRECT_URIS 固定 Web 回调)
deployments/production/.env.example 补 TokenDance ID OIDC 说明段(从已删 legacy env 模板迁移,仅注释)
docs/architecture/05-deployment.md inventory 表更新为最终形态(已删除/保留项)、遗留清单关闭语义更新

未修改:.github/workflows/checks.ymlrelease.ymlcd-hub-server.yml(任务书禁止)。

负向证明

  1. 第二份手维护 production compose 必 FAIL(回归)verify-deployment-shape.Tests.ps1 负例 1 通过 —— 在 fixture 的 deployments/production/ 下新增 docker-compose.us2.yml 时 verifier 以"second hand-maintained production compose"理由退出非零。
  2. legacy compose 复活必 FAIL:负例 2 通过 —— hub-server/deployments/ 下新增任何 compose 文件即 FAIL(关闭态)。
  3. 被删 legacy 不再被 workflow/verifier 引用(rg 证明)rg 全仓(排除 docs/archives、docs/archive 冻结历史)仅命中 docs/architecture/05-deployment.md 一处 —— 即本 PR 的 inventory 表(以"已删除"标注的最终形态记录,非活引用)。
  4. docker compose config 全通过:权威模板及收口前 legacy 三份均 config 解析成功(exit 0);本 PR 后仓库内唯一生产 compose 为权威模板。

范围声明

  • 未删除 hub-server/deployments/Dockerfile(构建输入,构建消费者真实存在)。
  • 未修改真实服务器 IP/域名/secret/SSH 配置;未触碰外部 server SSOT;未执行生产部署。
  • 未用注释代替机器防漂移:legacy 关闭由 verifier 强制,文档仅记录结果。
  • 工具链备注:Windows CRLF 文件与写工具编码问题已在本地绕过(Edit 单行匹配 + ASCII python 脚本),不影响提交内容。

本地验证输出摘要

  • docker compose config(权威)→ exit 0
  • verify-deployment-shape.ps1 → PASS 4/4
  • verify-deployment-shape.Tests.ps1 → 5/5 PASS
  • verify-ci-gates.ps1 → ok;verify-doc-ssot.ps1 → ok
  • 全部 workflow yaml 解析 → ok;git diff --check → 干净
  • bash -n hub-server/deployments/docker-entrypoint.sh → 通过

Summary by CodeRabbit

  • Deployment

    • Standardized production deployment and rollback guidance around Docker Compose.
    • Added production environment documentation, including OAuth configuration and redirect policies.
    • Consolidated deployment documentation around the authoritative production configuration.
    • Removed legacy regional deployment files, scripts, proxy configurations, and environment templates.
  • Verification

    • Updated deployment readiness and repository checks to enforce the streamlined deployment structure.
    • Improved validation for production OAuth settings and legacy configuration removal.

Copilot AI review requested due to automatic review settings August 3, 2026 13:43

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Production deployment now uses the authoritative Compose configuration and relocated environment template. Legacy deployment scripts, Compose files, proxy configurations, templates, and operational assets are removed. Deployment checks and readiness tests enforce the new structure.

Changes

Production deployment consolidation

Layer / File(s) Summary
Compose deployment path
.github/workflows/cd-production.yml, .github/workflows/cd-pr-check.yml, deployments/production/.env.example, hub-server/deployments/README.md, docs/architecture/05-deployment.md, scripts/release/verify-web-deploy-readiness.ps1, hub-server/deployments/*
Workflows now deploy and roll back through the production Compose file. Documentation and readiness checks use the relocated production assets. Legacy deployment scripts, Compose files, proxy configurations, environment templates, and backup assets are removed.
Legacy inventory validation
scripts/verify/verify-deployment-shape.ps1, scripts/verify/tests/verify-deployment-shape.Tests.ps1
Deployment-shape validation rejects any Compose file under hub-server/deployments/**. Tests cover an empty legacy directory and legacy Compose-file resurrection.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CDWorkflow as cd-production.yml
  participant Compose as Docker Compose
  participant HubServer as hub-server
  participant API as Production API
  CDWorkflow->>Compose: Start production services
  Compose->>HubServer: Recreate hub-server with tagged image
  CDWorkflow->>API: Perform manual health verification
  CDWorkflow->>Compose: Inspect production logs
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题准确概括了收口 legacy compose 与部署脚本,并同步 cd-production 引用这一主要变更。
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/deploy-pr2

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

#1527 PR1(cfde8494)已确立 deployments/production/docker-compose.yml 为权威
production compose SSOT 并挂 verify-deployment-shape 门禁;本 PR 完成 PR2 收口:

- 删除 hub-server/deployments 下旧独立 PG+Redis 拓扑资产:docker-compose.prod.yml、
  docker-compose.us1.yml、hk2/(compose + deploy-hk2.sh + deploy-web-hk2.sh +
  nginx/env 模板)、deploy.sh、Caddyfile/Caddyfile.prod、.env.production.example、
  backup-cron、.dockerignore(构建上下文为仓库根,消费根 .dockerignore)。
- 保留构建输入:Dockerfile、docker-entrypoint.sh(Dockerfile COPY 依赖);
  README.md 精简为构建输入说明(verify-doc-ssot 要求保留 "Live host" marker)。
- verify-deployment-shape.ps1 遗留清单由"注册制"改为"关闭态":
  hub-server/deployments/ 下出现任何 compose 文件即 FAIL;自测 5/5 通过,
  含"新增第二份手维护 production compose 必 FAIL"回归。
- cd-pr-check.yml 移除 deploy.sh / .env.production.example 检查与 deploy.sh
  结构校验 step;cd-production.yml 部署/回滚/health-check 指引回显全部改指
  deployments/production/docker-compose.yml(仅引用同步,未动行为/权限/secrets)。
- verify-web-deploy-readiness.ps1 生产 OIDC 断言改指权威 compose + 权威
  .env.example(env 模板补 OIDC 回调/交换端点/loopback 说明段)。
- docs/architecture/05-deployment.md inventory 表更新为最终形态。

未删 Dockerfile,未触碰 checks.yml / release.yml / cd-hub-server.yml,
未修改真实服务器/secret/生产部署。

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/cd-production.yml:
- Around line 128-132: Update the staging deployment instructions at
.github/workflows/cd-production.yml lines 128-132 and the production deployment
instructions at .github/workflows/cd-production.yml lines 191-196 so Docker
Compose starts the image selected by this workflow rather than the default
latest image; consistently tag the pulled image as latest or pass the selected
image tag or digest to the compose deployment command at both sites.
- Around line 191-196: The production workflow references docker-build-push
outputs without declaring the job as a direct dependency. Update the needs
declarations for approve-production and deploy-production to include
docker-build-push, and add it to health-check as well if that job must access
the actual image tag and digest instead of N/A; preserve the existing approval
and deployment ordering.

In `@deployments/production/.env.example`:
- Around line 17-24: Remove real production addresses from
deployments/production/.env.example lines 17-24 and replace the OAuth callback
with a placeholder. In .github/workflows/cd-production.yml lines 194-196 and
270-273, replace concrete production API addresses with placeholders. In
scripts/release/verify-web-deploy-readiness.ps1 lines 183-188, load the required
production domains from protected external verification configuration rather
than hardcoding them; apply the same repository policy consistently across all
four sites.

In `@scripts/release/verify-web-deploy-readiness.ps1`:
- Around line 183-188: Update the readiness assertions in the verification
script to avoid hard-coded production domains or server addresses. Move the
concrete callback and endpoint values used by these Assert-Contains checks into
the external server SSOT or protected verification configuration, then have the
checks reuse those injected values while preserving validation of the production
environment and compose settings.

In `@scripts/verify/verify-deployment-shape.ps1`:
- Around line 127-136: The legacy compose inventory check in Get-ChildItem must
detect both .yml and .yaml compose filenames under the legacy deployment
directory. Update scripts/verify/verify-deployment-shape.ps1 lines 127-136
accordingly, and add a .yaml resurrection fixture plus an assertion for the same
“legacy compose inventory closed” failure reason in
scripts/verify/tests/verify-deployment-shape.Tests.ps1 lines 94-110.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: a66e47c1-0983-4036-980b-70c554fb6b3c

📥 Commits

Reviewing files that changed from the base of the PR and between 225fad3 and d19ea98.

📒 Files selected for processing (22)
  • .github/workflows/cd-pr-check.yml
  • .github/workflows/cd-production.yml
  • deployments/production/.env.example
  • docs/architecture/05-deployment.md
  • hub-server/deployments/.dockerignore
  • hub-server/deployments/.env.production.example
  • hub-server/deployments/Caddyfile
  • hub-server/deployments/Caddyfile.prod
  • hub-server/deployments/README.md
  • hub-server/deployments/backup-cron
  • hub-server/deployments/deploy.sh
  • hub-server/deployments/docker-compose.prod.yml
  • hub-server/deployments/docker-compose.us1.yml
  • hub-server/deployments/hk2/.env.example
  • hub-server/deployments/hk2/deploy-hk2.sh
  • hub-server/deployments/hk2/deploy-web-hk2.sh
  • hub-server/deployments/hk2/docker-compose.hk2.yml
  • hub-server/deployments/hk2/nginx-hk2-v2.conf
  • hub-server/deployments/hk2/nginx-hk2.conf
  • scripts/release/verify-web-deploy-readiness.ps1
  • scripts/verify/tests/verify-deployment-shape.Tests.ps1
  • scripts/verify/verify-deployment-shape.ps1
💤 Files with no reviewable changes (14)
  • hub-server/deployments/hk2/nginx-hk2.conf
  • hub-server/deployments/backup-cron
  • hub-server/deployments/hk2/docker-compose.hk2.yml
  • hub-server/deployments/hk2/nginx-hk2-v2.conf
  • hub-server/deployments/.dockerignore
  • hub-server/deployments/Caddyfile
  • hub-server/deployments/hk2/.env.example
  • hub-server/deployments/docker-compose.us1.yml
  • hub-server/deployments/Caddyfile.prod
  • hub-server/deployments/docker-compose.prod.yml
  • hub-server/deployments/.env.production.example
  • hub-server/deployments/deploy.sh
  • hub-server/deployments/hk2/deploy-hk2.sh
  • hub-server/deployments/hk2/deploy-web-hk2.sh

Comment on lines +128 to +132
echo " 2. 部署: docker compose -f deployments/production/docker-compose.yml up -d --no-build"
echo " (本次构建镜像: ghcr.io/tokendancelab/agenthub-hub-server:${{ needs.docker-build-push.outputs.image_tag }})"
echo " 3. 验证: curl -s http://localhost:8090/health/ready (应返回 status=ok 且 ready=true)"
echo ""
echo "部署脚本与指南: hub-server/deployments/deploy.sh / hub-server/deployments/README.md"
echo "部署形状与指南: deployments/production/docker-compose.yml / docs/architecture/05-deployment.md"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Make Compose consume the image selected by this workflow.

Both instructions pull ${image_tag}, but the authoritative Compose file starts the latest tag. A non-stable release can therefore start an older image.

  • .github/workflows/cd-production.yml#L128-L132: tag the pulled staging image as latest, or pass its tag or digest to Compose.
  • .github/workflows/cd-production.yml#L191-L196: apply the same image-selection mechanism in production.
🧰 Tools
🪛 zizmor (1.28.0)

[info] 129-129: code injection via template expansion (template-injection): may expand into attacker-controllable code

(template-injection)

📍 Affects 1 file
  • .github/workflows/cd-production.yml#L128-L132 (this comment)
  • .github/workflows/cd-production.yml#L191-L196
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/cd-production.yml around lines 128 - 132, Update the
staging deployment instructions at .github/workflows/cd-production.yml lines
128-132 and the production deployment instructions at
.github/workflows/cd-production.yml lines 191-196 so Docker Compose starts the
image selected by this workflow rather than the default latest image;
consistently tag the pulled image as latest or pass the selected image tag or
digest to the compose deployment command at both sites.

Comment on lines +191 to +196
echo " 2. 部署: docker compose -f deployments/production/docker-compose.yml up -d --no-build"
echo " (本次构建镜像: ghcr.io/tokendancelab/agenthub-hub-server:${{ needs.docker-build-push.outputs.image_tag }})"
echo " compose 模板含 healthcheck;部署后人工验证见下方清单。"
echo " 3. 手动复核: curl -s https://api.hub.vectorcontrol.tech/health"
echo ""
echo "部署脚本与指南: hub-server/deployments/deploy.sh / hub-server/deployments/README.md"
echo "部署形状与指南: deployments/production/docker-compose.yml / docs/architecture/05-deployment.md"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== workflow excerpt =="
cat -n .github/workflows/cd-production.yml | sed -n '1,240p'

echo
echo "== job/dependency references =="
python3 - <<'PY'
from pathlib import Path
import re

p = Path(".github/workflows/cd-production.yml")
text = p.read_text()
for job in re.findall(r'^[\w-]+:.*?(?=\n\w|$)', text, flags=re.S | re.M):
    first=line=0
    for i, j in enumerate(text.splitlines(), 1):
        if j.rstrip().startswith(job.rstrip()):
            first=j; line=i; break
    print(f"JOB {first.strip()} at line {line}")
    for m in re.finditer(r'^\s+(needs|uses|with)?:', job, flags=re.M):
        print(f" line {text.count(chr(10),0,m.start())+1}: {m.group(0).strip()}")
PY

echo
echo "== yaml structural parse for needs =="
python3 - <<'PY'
from pathlib import Path
import re

text = Path(".github/workflows/cd-production.yml").read_text()
jobs = {}
current = None
for line in text.splitlines():
    stripped = line.rstrip()
    depth = len(line) - len(line.lstrip())
    if stripped.endswith(":") and depth == 2 and not stripped.startswith("jobs:"):
        current = stripped[:-1]
        jobs.setdefault(current, {"needs": [], "refs": []})
        job = jobs[current]
    if current and depth == 4 and stripped.startswith("needs:"):
        # inline list
        m = re.match(r'needs:\s*\[(.*?)\]', stripped)
        if m: job["needs"].extend(x.strip() for x in m.group(1).split(","))
        else:
            # multiline list
            buf = [stripped]
            for nxt in text.splitlines()[text.splitlines().index(stripped):]:
                pass

print(json.dumps(jobs, indent=2, sort_keys=True))
PY

Repository: TokenDanceLab/AgentHub

Length of output: 12467


🌐 Web query:

GitHub Actions context needs only jobs listed in needs key indirect needs context

💡 Result:

In GitHub Actions, the needs context provides access only to the outputs and results of jobs explicitly defined as direct dependencies of the current job [1][2][3]. It does not include data from "indirect" or transitive dependencies—that is, jobs that your dependencies depend on [1][3]. Key technical points: - Scope: The needs object is only populated for jobs that have one or more jobs listed in their needs key [1]. - Direct Only: You can only reference <job_id> in the needs context if that specific job ID is explicitly listed in your current job's needs configuration [1][2][3]. Attempting to access an indirect dependency's output or result via the needs context will fail or result in an empty/undefined value [4][1]. - Propagation Behavior: While needs data is not transitively available, the lifecycle of jobs is still subject to the Directed Acyclic Graph (DAG) logic [5]. If a job fails or is skipped, GitHub Actions will propagate that status downstream, causing dependent jobs to be skipped unless they use conditional expressions like if: always() or if: !cancelled() to override the default behavior [6][5][7]. - Troubleshooting: If you require data from a job that is not a direct dependency, you must either explicitly add that job to the current job's needs array or pass the required information through an intermediate job [8][1]. Workaround patterns for conditional job execution often involve using if conditions to handle the inherited skipped status caused by upstream failures in the dependency chain [6][5].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== deploy-production job block =="
cat -n .github/workflows/cd-production.yml | sed -n '173,270p'

echo
echo "== jobs and direct needs =="
python3 - <<'PY'
import yaml
from pathlib import Path

doc = yaml.safe_load(Path(".github/workflows/cd-production.yml"))
for job_id, job in doc.get("jobs", {}).items():
    print(f"{job_id}: needs={job.get('needs')}, outputs={list(job.get('outputs', {}).keys())}")
PY

Repository: TokenDanceLab/AgentHub

Length of output: 6111


Make docker-build-push a direct dependency.

deploy-production lists only approve-production, but reads needs.docker-build-push.outputs.image_tag and image_digest. GitHub Actions exposes only direct needs, so these values can be empty unless the dependency is added through the approval job or forwarded via explicit job outputs.

Add docker-build-push to approve-production/deploy-production, and to health-check if it should receive the actual image values instead of N/A.

🧰 Tools
🪛 zizmor (1.28.0)

[info] 192-192: code injection via template expansion (template-injection): may expand into attacker-controllable code

(template-injection)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/cd-production.yml around lines 191 - 196, The production
workflow references docker-build-push outputs without declaring the job as a
direct dependency. Update the needs declarations for approve-production and
deploy-production to include docker-build-push, and add it to health-check as
well if that job must access the actual image tag and digest instead of N/A;
preserve the existing approval and deployment ordering.

Comment on lines +17 to +24
# ── TokenDance ID OIDC 说明(字段定义见 docker-compose.yml 同目录)──
# 生产 OAuth 回调为公网 Web 浏览器回调:
# https://hub.vectorcontrol.tech/auth/tokendance/callback
# Hub 在 Web/Desktop 提交 code、state、PKCE verifier、device 与 redirect_uri 后,
# 通过 POST /client/auth/oidc/callback 完成代码交换(Hub 侧交换端点)。
# http://127.0.0.1/callback 仅保留给 Desktop/native 动态 loopback 端口;
# 生产 compose 的 ALLOWED_REDIRECT_URIS 固定为 Web 回调,不放 loopback。
# OIDC client 注册与 secret 由 TokenDance ID 管理,禁止写入仓库。

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Remove real production server addresses from repository files.

The same repository-policy violation appears in environment guidance, deployment guidance, and readiness checks. Keep concrete production addresses in the external server SSOT.

  • deployments/production/.env.example#L17-L24: replace the concrete callback address with a placeholder.
  • .github/workflows/cd-production.yml#L194-L196: replace the concrete production API address with a placeholder.
  • .github/workflows/cd-production.yml#L270-L273: replace the concrete production API addresses with placeholders.
  • scripts/release/verify-web-deploy-readiness.ps1#L183-L188: inject concrete production domains through protected external verification configuration.

As per coding guidelines, “禁止提交 .env、API key、token、cookie、私钥、证书、SSH 配置、真实服务器或内网地址”.

📍 Affects 3 files
  • deployments/production/.env.example#L17-L24 (this comment)
  • .github/workflows/cd-production.yml#L194-L196
  • .github/workflows/cd-production.yml#L270-L273
  • scripts/release/verify-web-deploy-readiness.ps1#L183-L188
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@deployments/production/.env.example` around lines 17 - 24, Remove real
production addresses from deployments/production/.env.example lines 17-24 and
replace the OAuth callback with a placeholder. In
.github/workflows/cd-production.yml lines 194-196 and 270-273, replace concrete
production API addresses with placeholders. In
scripts/release/verify-web-deploy-readiness.ps1 lines 183-188, load the required
production domains from protected external verification configuration rather
than hardcoding them; apply the same repository policy consistently across all
four sites.

Source: Coding guidelines

Comment on lines +183 to +188
Assert-Contains "deployments\production\.env.example" "hub\.vectorcontrol\.tech/auth/tokendance/callback" "production env example uses Web browser callback as OAuth redirect"
Assert-Contains "deployments\production\.env.example" "POST /client/auth/oidc/callback" "production env example documents Hub exchange endpoint separately"
Assert-Contains "deployments\production\.env.example" "http://127\.0\.0\.1/callback" "production env example keeps Desktop/native loopback policy"
Assert-Contains "deployments\production\docker-compose.yml" "AGENTHUB_TOKENDANCE_ID_REDIRECT_URI: https://hub\.vectorcontrol\.tech/auth/tokendance/callback" "production compose uses Web browser callback as OAuth redirect"
Assert-Contains "deployments\production\docker-compose.yml" "AGENTHUB_TOKENDANCE_ID_ALLOWED_REDIRECT_URIS: https://hub\.vectorcontrol\.tech/auth/tokendance/callback" "production compose keeps Web callback as the only allowed redirect"
Assert-Contains "deployments\production\docker-compose.yml" "AGENTHUB_TOKENDANCE_ID_CLIENT_ID: \$\{AGENTHUB_TOKENDANCE_ID_CLIENT_ID:-\}" "production compose exposes OIDC client env overrides"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Remove real production server addresses from readiness checks.

These new regex checks commit real production domains. Move concrete production addresses to the external server SSOT, or inject them through protected verification configuration.

As per coding guidelines, “禁止提交 .env、API key、token、cookie、私钥、证书、SSH 配置、真实服务器或内网地址”.

🧰 Tools
🪛 PSScriptAnalyzer (1.25.0)

[info] 183-183: Cmdlet 'Assert-Contains' has positional parameter. Please use named parameters instead of positional parameters when calling a command.

(PSAvoidUsingPositionalParameters)


[info] 184-184: Cmdlet 'Assert-Contains' has positional parameter. Please use named parameters instead of positional parameters when calling a command.

(PSAvoidUsingPositionalParameters)


[info] 185-185: Cmdlet 'Assert-Contains' has positional parameter. Please use named parameters instead of positional parameters when calling a command.

(PSAvoidUsingPositionalParameters)


[info] 186-186: Cmdlet 'Assert-Contains' has positional parameter. Please use named parameters instead of positional parameters when calling a command.

(PSAvoidUsingPositionalParameters)


[info] 187-187: Cmdlet 'Assert-Contains' has positional parameter. Please use named parameters instead of positional parameters when calling a command.

(PSAvoidUsingPositionalParameters)


[info] 188-188: Cmdlet 'Assert-Contains' has positional parameter. Please use named parameters instead of positional parameters when calling a command.

(PSAvoidUsingPositionalParameters)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/release/verify-web-deploy-readiness.ps1` around lines 183 - 188,
Update the readiness assertions in the verification script to avoid hard-coded
production domains or server addresses. Move the concrete callback and endpoint
values used by these Assert-Contains checks into the external server SSOT or
protected verification configuration, then have the checks reuse those injected
values while preserving validation of the production environment and compose
settings.

Source: Coding guidelines

Comment on lines +127 to +136
# ── 4. Legacy compose inventory closed (PR2) ──────────────────────────────
# hub-server/deployments/ now holds build inputs only (Dockerfile,
# docker-entrypoint.sh, README.md). Any compose file there is a legacy
# resurrection and must FAIL.
$legacyComposes = @(Get-ChildItem -LiteralPath $LegacyDeployDir -Recurse -Filter "docker-compose*.yml" -File -ErrorAction SilentlyContinue)
foreach ($legacy in $legacyComposes) {
$relative = [IO.Path]::GetRelativePath($RepoRootPath, $legacy.FullName).Replace("\", "/")
$relativeToDeploy = $relative.Substring("hub-server/deployments/".Length)
if ($LegacyComposeNames -notcontains $relativeToDeploy) {
Fail-Verifier "unregistered legacy compose appears: $relative (register or migrate in #1527 PR2)"
}
}
if ($legacyComposes.Count -gt 0 -and $script:Failed -eq 0) {
Pass-Verifier "legacy compose inventory closed ($($legacyComposes.Count) registered file(s))"
if ($legacyComposes.Count -gt 0) {
$found = ($legacyComposes | ForEach-Object { [IO.Path]::GetRelativePath($RepoRootPath, $_.FullName).Replace("\", "/") }) -join ", "
Fail-Verifier "legacy compose inventory closed: compose files must not appear under hub-server/deployments/ (found: $found)"
} else {
Pass-Verifier "legacy compose inventory closed (no compose files under hub-server/deployments/)"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== files =="
git ls-files | rg '(^|/)verify-deployment-shape\.(ps1|Tests\.ps1)$|^scripts/verify/|^scripts/tests/'

echo
echo "== main verifier relevant lines =="
if [ -f scripts/verify/verify-deployment-shape.ps1 ]; then
  nl -ba scripts/verify/verify-deployment-shape.ps1 | sed -n '110,145p'
fi

echo
echo "== test relevant lines =="
if [ -f scripts/verify/tests/verify-deployment-shape.Tests.ps1 ]; then
  nl -ba scripts/verify/tests/verify-deployment-shape.Tests.ps1 | sed -n '70,125p'
fi

echo
echo "== docker-compose filename patterns in script/tests =="
rg -n 'docker-compose|compose\.|LegacyDeployDir|Get-ChildItem.*-Filter|Filter "docker-compose' scripts/verify/verify-deployment-shale.ps1 scripts/verify/verify-deployment-shape.ps1 scripts/verify/tests/verify-deployment-shape.Tests.ps1 2>/dev/null || true

echo
echo "== PowerShell FileInfo Filter behavior probe using documentation/source grep only? no execute repo =="
python3 - <<'PY'
from pathlib import Path
for p in [Path('scripts/verify/verify-deployment-shape.ps1'), Path('scripts/verify/tests/verify-deployment-shape.Tests.ps1')]:
    text = p.read_text()
    print(f"\n== {p} mentions docker-compose extensions ==")
    for i, line in enumerate(text.splitlines(), 1):
        if 'docker-compose' in line:
            print(f"{i}: {line}")
PY

Repository: TokenDanceLab/AgentHub

Length of output: 3307


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== script relevant lines =="
if [ -f scripts/verify/verify-deployment-shape.ps1 ]; then
  sed -n '115,145p' scripts/verify/verify-deployment-shape.ps1
fi

echo
echo "== test relevant lines =="
if [ -f scripts/verify/tests/verify-deployment-shape.Tests.ps1 ]; then
  sed -n '85,120p' scripts/verify/tests/verify-deployment-shape.Tests.ps1
fi

echo
echo "== compose filename patterns =="
rg -n 'docker-compose|\.yml|\.yaml|LegacyDeployDir' scripts/verify/verify-deployment-shape.ps1 scripts/verify/tests/verify-deployment-shape.Tests.ps1 2>/dev/null || true

Repository: TokenDanceLab/AgentHub

Length of output: 4972


🌐 Web query:

PowerShell Get-ChildItem -Filter wildcard matches *.yml does not match *.yaml case insensitive

💡 Result:

In PowerShell, the wildcard pattern .yml specifically matches files ending with the.yml extension and does not match files with the.yaml extension [1][2]. This behavior occurs because PowerShell wildcards perform a character-by-character pattern match rather than a semantic match for file extensions [1]. The asterisk () character represents any number of characters, but it must be followed by the exact literal sequence provided in your pattern [1]. To match both.yml and.yaml files, you should use one of the following methods: 1. Using the -Include parameter: This is often the most readable way to specify multiple patterns [2]. Get-ChildItem -Path. -Include *.yml, *.yaml 2. Using a regex-based filter with Where-Object: This offers the most precise control if you need to perform complex matching. Get-ChildItem -File | Where-Object { $_.Name -match '.ya?ml$' } 3. Using multiple arguments for -Path: Get-ChildItem -Path *.yml, *.yaml Note that wildcard matching in PowerShell is generally case-insensitive on Windows (which is the default behavior of the underlying file system) but may be case-sensitive on other operating systems depending on the file system configuration [1]. Avoid using the -Filter parameter if you need to pass multiple patterns simultaneously, as -Filter typically accepts only a single string pattern and delegates the matching to the underlying provider (often Win32 APIs), which does not support comma-separated list syntax [3].

Citations:


Close the .yaml compose-file bypass.

docker-compose*.yml does not match Compose files ending in .yaml, so a legacy .yaml compose file under hub-server/deployments/ is not flagged by the closed-inventory rule.

  • Update scripts/verify/verify-deployment-shape.ps1 to include .yaml compose filenames for the legacy legacy compose path.
  • Add a .yaml resurrection fixture in scripts/verify/tests/verify-deployment-shape.Tests.ps1 and assert the same legacy compose inventory closed failure reason.
🧰 Tools
🪛 PSScriptAnalyzer (1.25.0)

[warning] Missing BOM encoding for non-ASCII encoded file 'verify-deployment-shape.ps1'

(PSUseBOMForUnicodeEncodedFile)

📍 Affects 2 files
  • scripts/verify/verify-deployment-shape.ps1#L127-L136 (this comment)
  • scripts/verify/tests/verify-deployment-shape.Tests.ps1#L94-L110
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/verify/verify-deployment-shape.ps1` around lines 127 - 136, The
legacy compose inventory check in Get-ChildItem must detect both .yml and .yaml
compose filenames under the legacy deployment directory. Update
scripts/verify/verify-deployment-shape.ps1 lines 127-136 accordingly, and add a
.yaml resurrection fixture plus an assertion for the same “legacy compose
inventory closed” failure reason in
scripts/verify/tests/verify-deployment-shape.Tests.ps1 lines 94-110.

@DeliciousBuding
DeliciousBuding merged commit 83c628e into master Aug 3, 2026
28 checks passed
@DeliciousBuding
DeliciousBuding deleted the chore/deploy-pr2 branch August 3, 2026 16:05
DeliciousBuding added a commit that referenced this pull request Aug 11, 2026
…1590)

#1527 PR1(94a2644f)已确立 deployments/production/docker-compose.yml 为权威
production compose SSOT 并挂 verify-deployment-shape 门禁;本 PR 完成 PR2 收口:

- 删除 hub-server/deployments 下旧独立 PG+Redis 拓扑资产:docker-compose.prod.yml、
  docker-compose.us1.yml、hk2/(compose + deploy-hk2.sh + deploy-web-hk2.sh +
  nginx/env 模板)、deploy.sh、Caddyfile/Caddyfile.prod、.env.production.example、
  backup-cron、.dockerignore(构建上下文为仓库根,消费根 .dockerignore)。
- 保留构建输入:Dockerfile、docker-entrypoint.sh(Dockerfile COPY 依赖);
  README.md 精简为构建输入说明(verify-doc-ssot 要求保留 "Live host" marker)。
- verify-deployment-shape.ps1 遗留清单由"注册制"改为"关闭态":
  hub-server/deployments/ 下出现任何 compose 文件即 FAIL;自测 5/5 通过,
  含"新增第二份手维护 production compose 必 FAIL"回归。
- cd-pr-check.yml 移除 deploy.sh / .env.production.example 检查与 deploy.sh
  结构校验 step;cd-production.yml 部署/回滚/health-check 指引回显全部改指
  deployments/production/docker-compose.yml(仅引用同步,未动行为/权限/secrets)。
- verify-web-deploy-readiness.ps1 生产 OIDC 断言改指权威 compose + 权威
  .env.example(env 模板补 OIDC 回调/交换端点/loopback 说明段)。
- docs/architecture/05-deployment.md inventory 表更新为最终形态。

未删 Dockerfile,未触碰 checks.yml / release.yml / cd-hub-server.yml,
未修改真实服务器/secret/生产部署。

Co-authored-by: Codex <codex@vectorcontrol.tech>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants