From fdfb77c4a215e05383d9fb05acfb552f59fdc57a Mon Sep 17 00:00:00 2001 From: Zyy Date: Sun, 2 Aug 2026 04:27:49 +0800 Subject: [PATCH] ci(release): reuse caches across versions Dispatch releases from the long-lived publishing branch so Cargo caches are shared across version tags. Store prebuilt image caches in per-architecture GHCR refs and include toolchain and workspace manifests in Cargo cache invalidation. Co-authored-by: Codex --- .github/workflows/release.yml | 21 +++++++++------------ README.md | 7 ++++--- release/publish | 18 ++++++++++++++++++ 3 files changed, 31 insertions(+), 15 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 856ebf86f..0a57f72a6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,9 +1,6 @@ name: Release on: - push: - tags: - - 'v*' workflow_dispatch: inputs: tag: @@ -15,7 +12,7 @@ permissions: contents: read concurrency: - group: release-${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref_name }} + group: release-${{ inputs.tag }} cancel-in-progress: false env: @@ -43,14 +40,14 @@ jobs: - name: Checkout uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: - ref: ${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref }} + ref: ${{ inputs.tag }} fetch-depth: 0 - name: Read release metadata id: version shell: bash env: - RELEASE_TAG: ${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref_name }} + RELEASE_TAG: ${{ inputs.tag }} run: | ruby <<'RUBY' >> "$GITHUB_OUTPUT" require "json" @@ -188,9 +185,9 @@ jobs: ~/.cargo/registry ~/.cargo/git backend/target - key: cargo-${{ runner.os }}-${{ matrix.target }}-${{ hashFiles('backend/Cargo.lock') }} + key: cargo-v2-${{ runner.os }}-${{ matrix.target }}-${{ hashFiles('backend/Cargo.lock', 'backend/rust-toolchain.toml', 'backend/**/Cargo.toml', 'backend/.cargo/config.toml') }} restore-keys: | - cargo-${{ runner.os }}-${{ matrix.target }}- + cargo-v2-${{ runner.os }}-${{ matrix.target }}- - name: Build binary shell: bash @@ -253,9 +250,9 @@ jobs: ~/.cargo/registry ~/.cargo/git backend/target - key: cargo-${{ runner.os }}-${{ matrix.target }}-${{ hashFiles('backend/Cargo.lock') }} + key: cargo-v2-${{ runner.os }}-${{ matrix.target }}-${{ hashFiles('backend/Cargo.lock', 'backend/rust-toolchain.toml', 'backend/**/Cargo.toml', 'backend/.cargo/config.toml') }} restore-keys: | - cargo-${{ runner.os }}-${{ matrix.target }}- + cargo-v2-${{ runner.os }}-${{ matrix.target }}- - name: Build binary shell: bash @@ -471,8 +468,8 @@ jobs: push: true build-args: | CPR_PREBUILT_DIR=dist/docker - cache-from: type=gha,scope=runtime-prebuilt-${{ matrix.os }}-${{ matrix.arch }} - cache-to: type=gha,mode=max,scope=runtime-prebuilt-${{ matrix.os }}-${{ matrix.arch }} + cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache-${{ matrix.os }}-${{ matrix.arch }} + cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache-${{ matrix.os }}-${{ matrix.arch }},mode=min provenance: mode=max sbom: true labels: | diff --git a/README.md b/README.md index e581911eb..04ad80e17 100644 --- a/README.md +++ b/README.md @@ -182,9 +182,10 @@ upgrade 与真实客户端 IP;不要暴露 PostgreSQL 或 Redis。 release/publish ``` -脚本会更新 `release/version.yaml`、创建约定提交与带注释的 `v` tag,并原子推送分支和 tag。 -不要手工修改版本后单独打 tag。该脚本只发布仓库版本和触发 Release 构建,不会登录服务器,也不会 -改变任何运行实例;源码提交、仓库发版和实例升级是三个独立状态。 +脚本依赖已登录的 GitHub CLI(`gh auth login`)。它会更新 `release/version.yaml`、创建约定提交与带 +注释的 `v` tag,原子推送分支和 tag,再从发布分支触发 Release 构建,使构建缓存可以跨版本 +复用。不要手工修改版本后单独打 tag。该脚本不会登录服务器,也不会改变任何运行实例;源码提交、 +仓库发版和实例升级是三个独立状态。 ## 文档 diff --git a/release/publish b/release/publish index 21fe2e2d6..17d6b62c6 100755 --- a/release/publish +++ b/release/publish @@ -67,8 +67,11 @@ fi } require_command git +require_command gh require_command ruby +gh auth status >/dev/null 2>&1 || die "gh authentication is required; run gh auth login first" + version="${1#v}" [[ "$version" =~ $SEMVER ]] || die "version must be semver, for example 0.1.4" @@ -83,6 +86,9 @@ merge_ref="$(git config --get "branch.$branch.merge" || true)" [[ -n "$remote" && -n "$merge_ref" ]] || die "current branch has no upstream" remote_branch="${merge_ref#refs/heads/}" [[ "$remote_branch" != "$merge_ref" && -n "$remote_branch" ]] || die "unsupported upstream ref: $merge_ref" +remote_url="$(git remote get-url "$remote")" || die "failed to resolve remote URL for $remote" +repository="$(gh repo view "$remote_url" --json nameWithOwner --jq '.nameWithOwner' 2>/dev/null)" || + die "failed to resolve GitHub repository for $remote_url" if ! git diff --quiet --ignore-submodules --; then die "tracked files have unstaged changes; commit or stash them first" @@ -129,8 +135,20 @@ git commit \ git tag -a "$tag" -m "$tag" git push --atomic "$remote" "HEAD:$remote_branch" "refs/tags/$tag" +# Dispatch from the long-lived release branch instead of the tag so GitHub +# Actions caches remain reusable across releases. +if ! gh workflow run release.yml \ + --repo "$repository" \ + --ref "$remote_branch" \ + --raw-field "tag=$tag"; then + echo "error: commit and tag were pushed, but the Release workflow was not dispatched" >&2 + echo "retry: gh workflow run release.yml --repo $repository --ref $remote_branch --raw-field tag=$tag" >&2 + exit 1 +fi + cat <