Skip to content

ci(release): gate supported database upgrades on installed artifacts - #2181

Open
Zxf-xufeng wants to merge 1 commit into
masterfrom
codex/issue-2161-upgrade-release-gate
Open

Zxf-xufeng wants to merge 1 commit into
masterfrom
codex/issue-2161-upgrade-release-gate

Conversation

@Zxf-xufeng

Copy link
Copy Markdown
Member

Which issue or RFC does this PR close?

Closes #2161. Related: #2154, #2160, and RFC #1771.

Rationale for this change

A complete database created by an older Server can be rejected at startup even when limited migration tests pass. Releases need to declare exactly which upgrades they support and validate those claims against installed release artifacts before publishing packages.

What changes are included in this PR?

  • Add an explicit source/target/backend/configuration support policy. The current policy is fresh-install-only, with no supported production upgrade combinations while feat(migrations): complete the reusable upgrade framework from RFC #1771 and PR #1772 #2154 is incomplete.
  • Add a reusable acceptance runner that installs the exact source release and target wheel in separate environments. Advertised cases must execute all required phases: historical database creation, public migration commands, target startup, read/write/retrieval, authorization, Candidates/processing, history/cursors, and fresh/upgraded equivalence. Missing suites, skips, failures, stale reports, or missing backend evidence fail the gate.
  • Require a compatibility review bound to the persistence inputs when they change. The digest is a conservative review trigger, not an inference of semantic compatibility or a replacement for executable migration acceptance.
  • Run the gate in PR/master CI and before distribution upload in the release workflow. Both PyPI and Release asset jobs depend on that build. Gate local make publish as well, and retain evidence tied to the policy and actual wheel.
  • Reproduce the existing upgrade rejection paths with a database created and populated by an actual installed 1.3.0 SQLite Server. This negative regression is explicitly separate from successful upgrade acceptance.
  • Synchronize bilingual installation notices with the matrix, require matching GitHub Release notes, and document the release procedure and the contract for future backend suites.

Are there any user-facing changes?

The installation guides explicitly state that existing Server database upgrades are currently unsupported and remove commands implying a working full upgrade path. Release publication now requires a matching support declaration in the release notes.

This PR does not implement the migration chain in #2154 or claim successful SQLite, seekDB, or OceanBase upgrades. Positive backend suites must accompany their corresponding support-matrix entries when that implementation is ready. The present negative SQLite fixture must then be replaced with supported-path acceptance.

Repository administrators must configure Upgrade release gate as a required branch-protection check. The release workflow is triggered by release.published, so it gates packages and attachments, not the preceding manual publication of the Release page; the documented prepublication command covers that step.

How was this change tested?

  • make check — passed, including all pre-commit hooks, type checks, action pin checks, release-reference checks, and integration manifest checks.
  • uv run prek run -a — passed with the new files staged.
  • pytest -q tests/test_upgrade_release_gate.py tests/test_release_version.py tests/test_ci_release_verification.py — 60 passed.
  • Built a wheel from the master-based checkout and executed the fresh-install-only policy gate against it; evidence explicitly records zero supported upgrade combinations.
  • scripts/ci_legacy_upgrade_rejection.py --wheel <built-wheel> --output <new-directory> — passed against installed 1.3.0 and 1.4.1.dev85+g2d11abd6a.d20261021, Python 3.12.13 / SQLite 3.53.1. The source Server created 81 tables and persisted/retrieved Memory through HTTP. Target migration status returned unknown_baseline; startup returned migration_required; startup against a separate copy with the prototype revision table returned migration_framework_not_ready. That last fixture is not a successfully migrated database.

AI usage statement

Implemented and validated with OpenAI Codex (GPT-6 family), under maintainer direction.

"""
inputs = [root / relative for relative in MANAGED_INPUTS]
files = {
path.relative_to(root).as_posix(): sha256(path)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[P2] managed_digest 对工作树字节取哈希,Windows 检出上必然误报持久化变更

managed_digest() 直接 sha256(path.read_bytes()),比较对象是提交在 release/upgrade-support.json 里的常量。.gitattributes 没有为 src/powercontext/builtin/persistence/**、builtin/code/**、server/authz/** 等受管输入声明 eol=lf,因此 core.autocrlf=true 的 Windows 检出会把它们全部转成 CRLF。

实测(同一 commit d7f2d897,同一棵树、只有行尾不同):

  • CRLF 工作树:6b533d6e15f1de1a50d2885f1fce4406c64cc16f6b495eb02cd293f5daad93d7
  • 逐文件把 \r\n 归一为 \n 后:ca3b475f2d0c883e19291a8d8b1dadbe50f93ebd93aad550a9112a3497737927 = 声明值

即唯一差异就是行尾,却会让已并入 make check / make release-check 的 upgrade-policy-check 失败,报错是 Persistence changed: update the compatibility review。Windows 贡献者若照提示改那个常量,写进去的是 CRLF 派生值,Linux CI 上又会红——错误信息把行尾噪声说成了兼容性变更,代价是两边来回改。

建议:

  1. 哈希前归一化行尾(path.read_bytes().replace(b"\r\n", b"\n")),或对 MANAGED_INPUTS 全覆盖声明 text eol=lf,让检出与 blob 一致;
  2. 失败信息区分「文件内容集合变化」与「仅行尾差异」,避免把人引向改常量。

@AlexStocks AlexStocks added the 1.4.1 v1.4.1 release tracking label Oct 21, 2026

@hidb4ai hidb4ai left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One additional P2 in the local publication path. The CRLF digest issue is already covered by the existing review thread.

Comment thread Makefile
.PHONY: publish
publish: ## Publish a release to PyPI.
publish: ## Publish after release upgrade acceptance; UPGRADE_RELEASE_NOTES must name the reviewed release notes file.
@uv run python scripts/run_upgrade_release_gate.py --release --release-notes "$$UPGRADE_RELEASE_NOTES"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[P2] Validate the complete set of distributions before publishing

The runner checks only dist/*.whl, but this recipe subsequently uploads dist/*. In a controlled fixture with a policy-matching 1.4.0 wheel and a leftover 1.3.0 sdist, the gate passed and both files were selected for upload (the upload was intercepted). The sdist therefore bypasses the target-version and acceptance checks; an older build of a same-version sdist would also remain unchecked. Validate the complete publication set and restrict the upload to those validated artifacts.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

1.4.1 v1.4.1 release tracking

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ci(release): gate supported upgrades on complete databases from actual prior releases

3 participants