diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 96096be..3cd3d19 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -46,6 +46,7 @@ jobs: echo "repository=ghcr.io/${owner}/imagesilo" >> "$GITHUB_OUTPUT" quality: + name: Release quality needs: preflight runs-on: ubuntu-24.04 timeout-minutes: 20 @@ -72,7 +73,8 @@ jobs: - name: Run release quality gate run: make check e2e - platform-image: + release-smoke: + name: Release smoke and publish (${{ matrix.suffix }}) needs: [preflight, quality] permissions: contents: read @@ -86,11 +88,13 @@ jobs: architecture: amd64 suffix: amd64 port: 18100 + benchmark_port: 18110 - runner: ubuntu-24.04-arm platform: linux/arm64 architecture: arm64 suffix: arm64 port: 18101 + benchmark_port: 18111 runs-on: ${{ matrix.runner }} timeout-minutes: 35 env: @@ -105,6 +109,17 @@ jobs: with: go-version-file: .go-version cache: true + - name: Benchmark delivery index + run: | + output="delivery-index-benchmark-${{ matrix.suffix }}.jsonl" + go run ./tests/performance/delivery_index_benchmark | tee "$output" + jq --exit-status --slurp 'all(.[]; .lookupFailures == 0 and .bytesPerPath < 1024)' "$output" >/dev/null + { + echo "### Native ${{ matrix.suffix }} delivery index benchmark" + echo '```json' + cat "$output" + echo '```' + } >> "$GITHUB_STEP_SUMMARY" - name: Resolve immutable image references id: image shell: bash @@ -171,6 +186,28 @@ jobs: PORT: ${{ matrix.port }} SMOKE_SUFFIX: release-${{ matrix.suffix }} run: bash scripts/container-smoke.sh + - name: Benchmark native processing at concurrency 1 + if: steps.state.outputs.mode == 'build' + env: + IMAGE: ${{ steps.image.outputs.content_target }} + PLATFORM: ${{ matrix.platform }} + PORT: ${{ matrix.benchmark_port }} + BENCH_SUFFIX: release-${{ matrix.suffix }} + CONCURRENCIES: "1" + CPU_LIMIT: "1" + MEMORY_LIMIT: 768m + PIDS_LIMIT: "256" + MAX_MEMORY_PEAK_BYTES: "536870912" + MAX_P95_MILLISECONDS: "20000" + run: | + output="processing-benchmark-${{ matrix.suffix }}.jsonl" + bash scripts/processing-benchmark.sh | tee "$output" + { + echo "### Native ${{ matrix.suffix }} processing benchmark (concurrency 1)" + echo '```json' + cat "$output" + echo '```' + } >> "$GITHUB_STEP_SUMMARY" - name: Publish new immutable platform content if: steps.state.outputs.mode == 'build' shell: bash @@ -209,7 +246,8 @@ jobs: echo "digest=$platform_digest" >> "$GITHUB_OUTPUT" manifest: - needs: [preflight, platform-image] + name: Publish release manifest + needs: [preflight, release-smoke] runs-on: ubuntu-24.04 timeout-minutes: 10 permissions: diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index 78f4ce5..0fefa1d 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml @@ -1,4 +1,4 @@ -name: Verify +name: Quick verify on: pull_request: @@ -29,73 +29,5 @@ jobs: cache-dependency-path: web/package-lock.json - name: Install frontend dependencies run: npm --prefix web ci - - name: Run quality gate + - name: Run quick quality gate run: make check e2e - - container-smoke: - needs: quality - strategy: - fail-fast: false - matrix: - include: - - runner: ubuntu-24.04 - platform: linux/amd64 - suffix: amd64 - port: 18080 - benchmark_port: 18090 - - runner: ubuntu-24.04-arm - platform: linux/arm64 - suffix: arm64 - port: 18081 - benchmark_port: 18091 - runs-on: ${{ matrix.runner }} - timeout-minutes: 30 - steps: - - name: Check out source - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - - name: Set up Go - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 - with: - go-version-file: .go-version - cache: true - - name: Benchmark delivery index - run: | - output="delivery-index-benchmark-${{ matrix.suffix }}.jsonl" - go run ./tests/performance/delivery_index_benchmark | tee "$output" - jq --exit-status --slurp 'all(.[]; .lookupFailures == 0 and .bytesPerPath < 1024)' "$output" >/dev/null - { - echo "### Native ${{ matrix.suffix }} delivery index benchmark" - echo '```json' - cat "$output" - echo '```' - } >> "$GITHUB_STEP_SUMMARY" - - name: Build native container image - run: docker build --platform "${{ matrix.platform }}" --file deploy/docker/Dockerfile --tag "imagesilo:smoke-${{ matrix.suffix }}" . - - name: Run login, upload, delivery, and restart smoke test - env: - IMAGE: imagesilo:smoke-${{ matrix.suffix }} - PLATFORM: ${{ matrix.platform }} - PORT: ${{ matrix.port }} - SMOKE_SUFFIX: ${{ matrix.suffix }} - run: bash scripts/container-smoke.sh - - name: Benchmark native processing at concurrency 1 - env: - IMAGE: imagesilo:smoke-${{ matrix.suffix }} - PLATFORM: ${{ matrix.platform }} - PORT: ${{ matrix.benchmark_port }} - BENCH_SUFFIX: ${{ matrix.suffix }} - CONCURRENCIES: "1" - CPU_LIMIT: "1" - MEMORY_LIMIT: 768m - PIDS_LIMIT: "256" - MAX_MEMORY_PEAK_BYTES: "536870912" - MAX_P95_MILLISECONDS: "20000" - run: | - output="processing-benchmark-${{ matrix.suffix }}.jsonl" - bash scripts/processing-benchmark.sh | tee "$output" - { - echo "### Native ${{ matrix.suffix }} processing benchmark (concurrency 1)" - echo '```json' - cat "$output" - echo '```' - } >> "$GITHUB_STEP_SUMMARY" diff --git a/docs/ci.md b/docs/ci.md index 8cc33d5..14d1c62 100644 --- a/docs/ci.md +++ b/docs/ci.md @@ -1,20 +1,29 @@ # 自动化验证 -`.github/workflows/verify.yml` 使用固定 commit SHA 的官方 Actions: +## 快速校验 + +`.github/workflows/verify.yml` 是 PR、`main` push 和手动运行使用的快速门禁,并使用固定 commit SHA 的官方 Actions: - `actions/checkout` 7.0.1 - `actions/setup-go` 7.0.0 - `actions/setup-node` 7.0.0 -`quality` job 执行与本地一致的 `make check`。`container-smoke` 分别在 GitHub 官方 `ubuntu-24.04`(amd64)和 `ubuntu-24.04-arm`(arm64)原生 runner 上执行: +唯一的 `quality` job 执行 `make check e2e`,覆盖 Go、React、OpenAPI 生成一致性、Lint、类型检查、单元/集成测试和单 worker 浏览器闭环。该工作流不构建容器镜像、不运行容器 smoke,也不接触 GHCR;`quality` check 名称保持不变。 + +## Release smoke + +`.github/workflows/release.yml` 只接受属于 `origin/main` 的 `v*` Tag。Release 重新运行质量门后,分别在 GitHub 官方 `ubuntu-24.04`(amd64)和 `ubuntu-24.04-arm`(arm64)原生 runner 上执行: -1. 构建目标架构镜像。 -2. 通过 `--password-stdin` 创建临时管理员,密码不进入进程参数。 -3. 登录并取得 Session Cookie。 -4. 流式上传确定性 JPEG。 -5. 核对公开 URL 的 SHA-256、非 root 用户和健康检查。 -6. 停止容器、使用同一 named volume 重启并再次核对 URL。 -7. 无论成功或失败都删除临时容器、volume、Cookie 和响应文件。 +1. 执行原生 Delivery Index benchmark。 +2. 构建目标架构镜像。 +3. 通过 `--password-stdin` 创建临时管理员,密码不进入进程参数。 +4. 登录并取得 Session Cookie。 +5. 流式上传确定性 JPEG。 +6. 核对公开 URL 的 SHA-256、非 root 用户和健康检查。 +7. 停止容器、使用同一 named volume 重启并再次核对 URL。 +8. 对同一镜像执行并发 `1` 的原生图片处理 benchmark。 +9. 无论成功或失败都删除临时容器、volume、Cookie 和响应文件。 +10. 只有该架构全部 smoke/benchmark 成功后才推送对应的不可变平台镜像;只有两个架构都成功后才创建版本与 `latest` manifest。 本地可使用相同脚本: @@ -26,4 +35,4 @@ SMOKE_SUFFIX=local-arm64 \ bash scripts/container-smoke.sh ``` -首次原生双架构运行证据为 [Verify run 30447890938](https://github.com/Willxup/imagesilo/actions/runs/30447890938):质量门、amd64 容器闭环和 arm64 容器闭环全部成功。Git 推送通过仓库 SSH 远程完成;后续正常开发提交按相同工作流持续验证。 +首次原生双架构运行证据为 [Verify run 30447890938](https://github.com/Willxup/imagesilo/actions/runs/30447890938):质量门、amd64 容器闭环和 arm64 容器闭环全部成功。该记录保留为历史证据;当前开发提交只运行快速校验,双架构容器 smoke 已收敛到 Release Tag 流程。 diff --git a/docs/development-status.md b/docs/development-status.md index 0329676..89fdd87 100644 --- a/docs/development-status.md +++ b/docs/development-status.md @@ -61,7 +61,7 @@ 阶段 7 已完成。GitHub Actions [Release image run 30505989284](https://github.com/Willxup/imagesilo/actions/runs/30505989284) 由 `v0.1.0-rc.1` tag push 自动触发并全部成功;公开 GHCR 多架构镜像和 [GitHub Pre-release](https://github.com/Willxup/imagesilo/releases/tag/v0.1.0-rc.1) 均已验证。 -`.github/workflows/verify.yml` 和 `scripts/container-smoke.sh` 已成为后续提交的固定阶段门。脚本在本机和 GitHub 均确认成功/失败结束后不遗留临时容器或 named volume。 +`.github/workflows/verify.yml` 是后续提交的快速质量门;双架构 `scripts/container-smoke.sh` 只在 Release Tag 流程执行,并在对应架构 smoke 成功后才允许发布平台镜像。脚本在本机和 GitHub 均确认成功/失败结束后不遗留临时容器或 named volume。 ## 阶段门 diff --git a/docs/release.md b/docs/release.md index 45ffc40..d8268b6 100644 --- a/docs/release.md +++ b/docs/release.md @@ -2,9 +2,11 @@ ## 质量门 -`make check e2e` 覆盖全部 Go 包、React、OpenAPI 生成一致性和单 worker 浏览器闭环。`Verify` 工作流随后在原生 amd64、原生 arm64 各构建一次镜像、执行容器 smoke,并只运行并发 `1`、总计 `16` 个请求的图片处理 benchmark。Benchmark 容器限制为 1 CPU、768 MiB 和 256 PID,并强制要求全部请求成功、无 busy 响应、p95 不超过 20 秒且 cgroup 峰值不超过 512 MiB。 +PR 的 `Quick verify` 工作流只执行 `make check e2e`,覆盖全部 Go 包、React、OpenAPI 生成一致性和单 worker 浏览器闭环,不构建容器镜像。推送 Release Tag 后,`Release image` 工作流重新执行质量门,再在原生 amd64、原生 arm64 执行 Delivery Index benchmark、构建镜像、容器 smoke 和并发 `1` 的图片处理 benchmark。只有全部验证成功的同一镜像才会推送对应平台标签;两个架构都成功后才创建版本与 `latest` manifest。 -容器 smoke 还会验证: +图片处理 benchmark 每个架构总计 `16` 个请求,容器限制为 1 CPU、768 MiB 和 256 PID,并强制要求全部请求成功、无 busy 响应、p95 不超过 20 秒且 cgroup 峰值不超过 512 MiB。 + +Release smoke 还会验证: - 公开标准 URL 和别名的 Range、条件请求、HEAD 与相同 ETag。 - 固定 `10001:10001`、exec-form ENTRYPOINT 和内置健康检查。