From a975868046196b069ae28bc875d431fc04d0b2f4 Mon Sep 17 00:00:00 2001 From: Zyy Date: Tue, 15 Sep 2026 15:02:49 +0800 Subject: [PATCH] fix(release): publish version-matched deployment assets Publish the configuration template and Compose file with release checksums, pin the packaged Compose image to the release version, and include the template in platform archives. Download deployment assets from one release tag, link versioned deployment documentation, and translate the release installation notes into Chinese. Validated Actionlint, stable and prerelease packaging for all platforms, SHA-256 checksums, and resolved Docker Compose image versions. Co-authored-by: Codex --- .github/workflows/release.yml | 45 ++++++++++++++++++++++++----------- README.md | 12 +++++++--- deploy/README.md | 8 ++++++- 3 files changed, 47 insertions(+), 18 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3d8d363d5..2829f958e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -315,6 +315,7 @@ jobs: shell: bash env: VERSION: ${{ needs.release-info.outputs.version }} + DOCKER_VERSION: ${{ needs.release-info.outputs.docker_version }} run: | set -euo pipefail ruby <<'RUBY' > release-platforms.json @@ -349,7 +350,18 @@ jobs: shutil.rmtree(release_dir, ignore_errors=True) release_dir.mkdir(parents=True) - archives = [] + config_template = pathlib.Path("deploy/config.example.yaml") + shutil.copy2(config_template, release_dir / config_template.name) + compose = pathlib.Path("deploy/compose.yaml").read_text() + image = f"{os.environ['REGISTRY']}/{os.environ['IMAGE_NAME']}" + default_image = "${CPR_IMAGE:-" + image + ":latest}" + if compose.count(default_image) != 1: + raise SystemExit("Expected exactly one default application image in deploy/compose.yaml") + # 发布附件固定镜像版本,防止后续 pull 与随包配置模板脱节。 + versioned_image = "${CPR_IMAGE:-" + f"{image}:{os.environ['DOCKER_VERSION']}" + "}" + compose = compose.replace(default_image, versioned_image) + (release_dir / "compose.yaml").write_text(compose) + assets = [release_dir / config_template.name, release_dir / "compose.yaml"] for platform in platforms: platform_name = f"{platform['os']}-{platform['arch']}" @@ -367,6 +379,9 @@ jobs: shutil.copy2(binary_src, binary_dest) binary_dest.chmod(0o755) shutil.copytree(frontend_dir, web_dist, dirs_exist_ok=True) + deploy_dir = package_root / "deploy" + deploy_dir.mkdir() + shutil.copy2(config_template, deploy_dir / config_template.name) archive_name = f"{APP_NAME}_{version}_{platform['os']}_{platform['arch']}.{platform['archive']}" archive_path = release_dir / archive_name @@ -375,12 +390,12 @@ jobs: archive.add(package_root, arcname=APP_NAME) else: raise SystemExit(f"Unsupported archive format: {platform['archive']}") - archives.append(archive_path) + assets.append(archive_path) checksum_path = release_dir / "checksums.txt" with checksum_path.open("w", encoding="utf-8") as file: - for archive in archives: - file.write(f"{sha256(archive)} {archive.name}\n") + for asset in assets: + file.write(f"{sha256(asset)} {asset.name}\n") PY - name: Generate release asset provenance @@ -655,25 +670,27 @@ jobs: env: INSTALLATION_NOTES: | > [!WARNING] - > **Upgrading across major versions?** Online upgrades across major versions are not supported. Deploy the new major fresh with a new `.runtime/` data directory, then re-import or re-authorize provider accounts and client keys. See the [upgrade notes](https://github.com/${{ github.repository }}/blob/main/deploy/README.md#镜像升级与源码构建). + > **跨大版本升级:** 不支持跨大版本在线升级。请使用全新的 `.runtime/` 数据目录重新部署,再重新导入或重新授权服务商账号,并重新导入客户端密钥。详见[升级说明](https://github.com/${{ github.repository }}/blob/${{ needs.release-info.outputs.tag }}/deploy/README.md#镜像升级与源码构建)。 - ## 📥 Installation + ## 📥 安装 - **Docker:** + **Docker 部署:** ```bash - # GitHub Container Registry + # 从 GitHub 容器镜像仓库拉取 docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.release-info.outputs.docker_version }} ``` - **Manual download:** - Download the appropriate archive for your platform from the assets below. + 请从本版本附件下载 `compose.yaml` 和 `config.example.yaml`。Compose 默认固定到本版本镜像;升级前请对比模板与已有配置。 - Release archives are covered by GitHub artifact attestations. Docker images are published with SBOM/provenance attestations and keyless cosign signatures. + **手动下载:** + 请从下方附件中下载适合当前平台的归档包。 - ## 📚 Documentation + 发布归档提供 GitHub 构建产物证明。Docker 镜像附带软件物料清单(SBOM)、构建来源证明和 cosign 无密钥签名。 - - [GitHub Repository](https://github.com/${{ github.repository }}) - - [Installation Guide](https://github.com/${{ github.repository }}/blob/main/deploy/README.md) + ## 📚 文档 + + - [GitHub 仓库](https://github.com/${{ github.repository }}) + - [部署指南](https://github.com/${{ github.repository }}/blob/${{ needs.release-info.outputs.tag }}/deploy/README.md) run: | python3 <<'PY' import os diff --git a/README.md b/README.md index fab5f702f..a371a4d29 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ ## 快速开始 -使用 Docker Compose 部署发布镜像 `ghcr.io/zyycn/codex-proxy-rs:latest`,同时启动 PostgreSQL 和 Redis。 +使用 Docker Compose 部署版本固定的发布镜像,同时启动 PostgreSQL 和 Redis。 以下命令适用于 Linux amd64/arm64,需要 Docker Engine、Docker Compose Plugin、curl 和 OpenSSL。已有部署请先看 [升级说明](deploy/README.md#镜像升级与源码构建),不要覆盖原配置。 @@ -30,9 +30,12 @@ ```bash mkdir -p codex-proxy-rs/deploy && cd codex-proxy-rs -curl -fsSL https://raw.githubusercontent.com/zyycn/codex-proxy-rs/main/deploy/compose.yaml \ +# 只解析一次最新正式版本,确保两个文件来自同一 Release。 +CPR_RELEASE_URL="$(curl -fsSL -o /dev/null -w '%{url_effective}' https://github.com/zyycn/codex-proxy-rs/releases/latest)" +CPR_RELEASE_TAG="${CPR_RELEASE_URL##*/}" +curl -fsSL "https://github.com/zyycn/codex-proxy-rs/releases/download/${CPR_RELEASE_TAG}/compose.yaml" \ -o deploy/compose.yaml -curl -fsSL https://raw.githubusercontent.com/zyycn/codex-proxy-rs/main/deploy/config.example.yaml \ +curl -fsSL "https://github.com/zyycn/codex-proxy-rs/releases/download/${CPR_RELEASE_TAG}/config.example.yaml" \ -o deploy/config.example.yaml install -d -m 0750 .runtime/postgres .runtime/redis @@ -40,6 +43,9 @@ sudo install -d -m 0770 -o "$(id -u)" -g 10001 .runtime/data .runtime/logs sudo install -m 0640 -o "$(id -u)" -g 10001 deploy/config.example.yaml deploy/config.yaml ``` +也可将 `CPR_RELEASE_TAG` 设置为指定的发布标签。Release 附带的 `compose.yaml` 默认使用该版本镜像, +配置模板和部署文件均包含在 `checksums.txt` 中;不要混用 `main` 分支模板与已发布镜像。 + 分别生成数据库和 Redis 密码: ```bash diff --git a/deploy/README.md b/deploy/README.md index a059efeb5..9b330a14c 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -332,7 +332,13 @@ OpenAI 主动额度重置卡及其消费结果由上游持有,不写入 Postgr > 以下命令只适用于同一大版本内的升级,不支持跨大版本在线升级。跨大版本请使用全新的 > `.runtime/` 数据目录重新部署,并重新导入或重新授权 Provider 账号与客户端 Key。 -Docker 安装从安装目录拉取发布镜像并重建应用容器: +每个 Release 独立提供 `config.example.yaml`、默认镜像固定到该版本的 `compose.yaml` 和校验和; +各平台归档也包含 `deploy/config.example.yaml`。配置模板来自构建该版本的同一提交。 +使用二进制归档手动部署时,将模板中的 `api.asset_directory` 改为 `../web/dist`,指向归档内的静态资源。 +升级时先阅读目标版本说明,下载同一 Release 的部署附件,对比模板并合并必要配置,保留已有凭据 +和 Compose 自定义项。不要用模板覆盖 `config.yaml`,也不要从 `main` 下载模板搭配旧镜像。 + +更新部署文件后,从安装目录拉取目标版本镜像并重建应用容器: ```bash docker compose -f deploy/compose.yaml pull codex-proxy-rs