build: add version synchronization gate
This commit is contained in:
parent
68579c4c86
commit
e5b7425f3a
|
|
@ -1,30 +1,14 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# Pre-commit hook: read version from branch name (e.g. v0.5.0)
|
||||
# and sync to all package.json files
|
||||
#
|
||||
set -eu
|
||||
|
||||
BRANCH=$(git rev-parse --abbrev-ref HEAD)
|
||||
script_dir=$(CDPATH= cd "$(dirname "$0")" && pwd)
|
||||
repo_root=$(CDPATH= cd "$script_dir/.." && pwd)
|
||||
cd "$repo_root"
|
||||
|
||||
# Extract version from branch name like v0.5.0, v1.2.3, release/v2.0.0
|
||||
VERSION=$(echo "$BRANCH" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' || true)
|
||||
|
||||
if [ -n "$VERSION" ]; then
|
||||
CHANGED=0
|
||||
for f in package.json apps/*/package.json packages/*/package.json; do
|
||||
if [ -f "$f" ]; then
|
||||
CURRENT=$(jq -r '.version' "$f")
|
||||
if [ "$CURRENT" != "$VERSION" ]; then
|
||||
jq --arg v "$VERSION" '.version=$v' "$f" > "$f.tmp" && mv "$f.tmp" "$f"
|
||||
git add "$f"
|
||||
CHANGED=1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$CHANGED" = "1" ]; then
|
||||
echo "[version-sync] branch $BRANCH → $VERSION"
|
||||
fi
|
||||
echo "[pre-commit] checking version consistency"
|
||||
if ! tools/check-version-sync.sh; then
|
||||
echo "[pre-commit] version consistency check failed. Run: scripts/sync-version.sh"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- Rust format + lint gates (same checks as CI) ---
|
||||
|
|
|
|||
102
.github/workflows/version-sync.yml
vendored
Normal file
102
.github/workflows/version-sync.yml
vendored
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
name: Version consistency
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- "Cargo.toml"
|
||||
- "Cargo.lock"
|
||||
- "crates/**/Cargo.toml"
|
||||
- "crates/op-cli/assets/skill-bundle.json"
|
||||
- "crates/op-cli/src/app_control_cli.rs"
|
||||
- "crates/op-editor-core/src/host_support.rs"
|
||||
- "crates/op-editor-core/src/state.rs"
|
||||
- "packages/package.json"
|
||||
- "packages/bun.lock"
|
||||
- "packages/op-web-sdk/package.json"
|
||||
- "packages/op-web-sdk/src/index.ts"
|
||||
- "packages/op-web-sdk-react/package.json"
|
||||
- "packages/op-web-sdk-react/src/index.ts"
|
||||
- "packages/op-web-sdk-vue/package.json"
|
||||
- "packages/op-web-sdk-vue/src/index.ts"
|
||||
- "packages/scripts/sync-version.mjs"
|
||||
- "packages/scripts/sync-version.test.mjs"
|
||||
- "scripts/workspace-version.sh"
|
||||
- "scripts/workspace-version.test.sh"
|
||||
- "scripts/sync-version.sh"
|
||||
- "scripts/sync-version.test.sh"
|
||||
- "scripts/bundle-macos.sh"
|
||||
- "scripts/package-windows.nsi"
|
||||
- "scripts/install-op.sh"
|
||||
- "tools/check-version-sync.sh"
|
||||
- "tools/check-version-sync.test.sh"
|
||||
- "tools/bundle-macos.sh"
|
||||
- ".githooks/pre-commit"
|
||||
- ".github/workflows/rust-release.yml"
|
||||
- ".github/workflows/version-sync.yml"
|
||||
push:
|
||||
paths:
|
||||
- "Cargo.toml"
|
||||
- "Cargo.lock"
|
||||
- "crates/**/Cargo.toml"
|
||||
- "crates/op-cli/assets/skill-bundle.json"
|
||||
- "crates/op-cli/src/app_control_cli.rs"
|
||||
- "crates/op-editor-core/src/host_support.rs"
|
||||
- "crates/op-editor-core/src/state.rs"
|
||||
- "packages/package.json"
|
||||
- "packages/bun.lock"
|
||||
- "packages/op-web-sdk/package.json"
|
||||
- "packages/op-web-sdk/src/index.ts"
|
||||
- "packages/op-web-sdk-react/package.json"
|
||||
- "packages/op-web-sdk-react/src/index.ts"
|
||||
- "packages/op-web-sdk-vue/package.json"
|
||||
- "packages/op-web-sdk-vue/src/index.ts"
|
||||
- "packages/scripts/sync-version.mjs"
|
||||
- "packages/scripts/sync-version.test.mjs"
|
||||
- "scripts/workspace-version.sh"
|
||||
- "scripts/workspace-version.test.sh"
|
||||
- "scripts/sync-version.sh"
|
||||
- "scripts/sync-version.test.sh"
|
||||
- "scripts/bundle-macos.sh"
|
||||
- "scripts/package-windows.nsi"
|
||||
- "scripts/install-op.sh"
|
||||
- "tools/check-version-sync.sh"
|
||||
- "tools/check-version-sync.test.sh"
|
||||
- "tools/bundle-macos.sh"
|
||||
- ".githooks/pre-commit"
|
||||
- ".github/workflows/rust-release.yml"
|
||||
- ".github/workflows/version-sync.yml"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
version-sync:
|
||||
name: Verify synchronized versions
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Install Rust
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
|
||||
- name: Install Bun
|
||||
uses: oven-sh/setup-bun@v2
|
||||
|
||||
- name: Install SDK dependencies
|
||||
working-directory: packages
|
||||
run: bun install --frozen-lockfile
|
||||
|
||||
- name: Test canonical version reader
|
||||
run: scripts/workspace-version.test.sh
|
||||
|
||||
- name: Test version synchronization entrypoint
|
||||
run: scripts/sync-version.test.sh
|
||||
|
||||
- name: Test repository version guard
|
||||
run: tools/check-version-sync.test.sh
|
||||
|
||||
- name: Check repository version consistency
|
||||
run: tools/check-version-sync.sh
|
||||
|
|
@ -23,7 +23,7 @@ Tooling is **Cargo** (Rust — the product). The root has **no `package.json`**;
|
|||
- **CLI:** `cargo build -p op-cli` → binary `op`
|
||||
- **MCP server:** built into the desktop/web host (`--mcp <path>`); crate `op-mcp`
|
||||
- **Iconify catalog (Rust assets):** from `packages/`: `bun run generate-iconify-catalog`
|
||||
- **Sync SDK versions:** from `packages/`: `bun run sync-version` (reads the canonical version from root `Cargo.toml`); verify with `bun run sync-version:check`
|
||||
- **Sync all managed versions:** `scripts/sync-version.sh` reads the canonical version from root `Cargo.toml`; verify without writing via `tools/check-version-sync.sh`
|
||||
|
||||
## Architecture
|
||||
|
||||
|
|
|
|||
|
|
@ -378,8 +378,8 @@ cargo run -p op-cli -- <args> # CLI (binary: op)
|
|||
# Web SDK / JS tooling (run from packages/)
|
||||
cd packages && bun run lint # Lint the web SDK (oxlint); also: bun run format
|
||||
cd packages && bun run generate-iconify-catalog # Regenerate the Rust icon catalog assets
|
||||
cd packages && bun run sync-version # Sync SDK versions from root Cargo.toml
|
||||
cd packages && bun run sync-version:check # Verify SDK versions match root Cargo.toml
|
||||
scripts/sync-version.sh # Sync all managed versions from root Cargo.toml
|
||||
tools/check-version-sync.sh # Verify all managed versions match root Cargo.toml
|
||||
```
|
||||
|
||||
## Mitwirken
|
||||
|
|
|
|||
|
|
@ -341,7 +341,7 @@ openpencil/
|
|||
│ ├── jian/ Framework de UI GPU-Skia — widgets/render/eventos
|
||||
│ ├── casement/ Fork de winit
|
||||
│ └── agent/ Runtime de agente Rust multi-producto (agent-rs)
|
||||
└── .githooks/ Sincronización de versión pre-commit desde nombre de rama
|
||||
└── .githooks/ Comprobación de coherencia de versiones en pre-commit
|
||||
```
|
||||
|
||||
## Atajos de Teclado
|
||||
|
|
@ -378,8 +378,8 @@ cargo run -p op-cli -- <args> # CLI (binary: op)
|
|||
# Web SDK / JS tooling (run from packages/)
|
||||
cd packages && bun run lint # Lint the web SDK (oxlint); also: bun run format
|
||||
cd packages && bun run generate-iconify-catalog # Regenerate the Rust icon catalog assets
|
||||
cd packages && bun run sync-version # Sync SDK versions from root Cargo.toml
|
||||
cd packages && bun run sync-version:check # Verify SDK versions match root Cargo.toml
|
||||
scripts/sync-version.sh # Sync all managed versions from root Cargo.toml
|
||||
tools/check-version-sync.sh # Verify all managed versions match root Cargo.toml
|
||||
```
|
||||
|
||||
## Contribuir
|
||||
|
|
|
|||
|
|
@ -341,7 +341,7 @@ openpencil/
|
|||
│ ├── jian/ Framework UI GPU-Skia — widgets/rendu/événements
|
||||
│ ├── casement/ Fork de winit
|
||||
│ └── agent/ Runtime d'agent Rust transversal (agent-rs)
|
||||
└── .githooks/ Synchronisation de version pre-commit depuis le nom de branche
|
||||
└── .githooks/ Vérification de cohérence des versions en pre-commit
|
||||
```
|
||||
|
||||
## Raccourcis clavier
|
||||
|
|
@ -378,8 +378,8 @@ cargo run -p op-cli -- <args> # CLI (binary: op)
|
|||
# Web SDK / JS tooling (run from packages/)
|
||||
cd packages && bun run lint # Lint the web SDK (oxlint); also: bun run format
|
||||
cd packages && bun run generate-iconify-catalog # Regenerate the Rust icon catalog assets
|
||||
cd packages && bun run sync-version # Sync SDK versions from root Cargo.toml
|
||||
cd packages && bun run sync-version:check # Verify SDK versions match root Cargo.toml
|
||||
scripts/sync-version.sh # Sync all managed versions from root Cargo.toml
|
||||
tools/check-version-sync.sh # Verify all managed versions match root Cargo.toml
|
||||
```
|
||||
|
||||
## Contribuer
|
||||
|
|
|
|||
|
|
@ -378,8 +378,8 @@ cargo run -p op-cli -- <args> # CLI (binary: op)
|
|||
# Web SDK / JS tooling (run from packages/)
|
||||
cd packages && bun run lint # Lint the web SDK (oxlint); also: bun run format
|
||||
cd packages && bun run generate-iconify-catalog # Regenerate the Rust icon catalog assets
|
||||
cd packages && bun run sync-version # Sync SDK versions from root Cargo.toml
|
||||
cd packages && bun run sync-version:check # Verify SDK versions match root Cargo.toml
|
||||
scripts/sync-version.sh # Sync all managed versions from root Cargo.toml
|
||||
tools/check-version-sync.sh # Verify all managed versions match root Cargo.toml
|
||||
```
|
||||
|
||||
## योगदान
|
||||
|
|
|
|||
|
|
@ -378,8 +378,8 @@ cargo run -p op-cli -- <args> # CLI (binary: op)
|
|||
# Web SDK / JS tooling (run from packages/)
|
||||
cd packages && bun run lint # Lint the web SDK (oxlint); also: bun run format
|
||||
cd packages && bun run generate-iconify-catalog # Regenerate the Rust icon catalog assets
|
||||
cd packages && bun run sync-version # Sync SDK versions from root Cargo.toml
|
||||
cd packages && bun run sync-version:check # Verify SDK versions match root Cargo.toml
|
||||
scripts/sync-version.sh # Sync all managed versions from root Cargo.toml
|
||||
tools/check-version-sync.sh # Verify all managed versions match root Cargo.toml
|
||||
```
|
||||
|
||||
## Berkontribusi
|
||||
|
|
|
|||
|
|
@ -378,8 +378,8 @@ cargo run -p op-cli -- <args> # CLI (binary: op)
|
|||
# Web SDK / JS tooling (run from packages/)
|
||||
cd packages && bun run lint # Lint the web SDK (oxlint); also: bun run format
|
||||
cd packages && bun run generate-iconify-catalog # Regenerate the Rust icon catalog assets
|
||||
cd packages && bun run sync-version # Sync SDK versions from root Cargo.toml
|
||||
cd packages && bun run sync-version:check # Verify SDK versions match root Cargo.toml
|
||||
scripts/sync-version.sh # Sync all managed versions from root Cargo.toml
|
||||
tools/check-version-sync.sh # Verify all managed versions match root Cargo.toml
|
||||
```
|
||||
|
||||
## コントリビュート
|
||||
|
|
|
|||
|
|
@ -341,7 +341,7 @@ openpencil/
|
|||
│ ├── jian/ GPU-Skia UI 프레임워크 — 위젯/렌더/이벤트
|
||||
│ ├── casement/ winit 포크
|
||||
│ └── agent/ 제품 공용 Rust 에이전트 런타임 (agent-rs)
|
||||
└── .githooks/ 브랜치 이름에서 버전 동기화를 위한 pre-commit
|
||||
└── .githooks/ pre-commit 버전 일관성 검사
|
||||
```
|
||||
|
||||
## 키보드 단축키
|
||||
|
|
@ -378,8 +378,8 @@ cargo run -p op-cli -- <args> # CLI (binary: op)
|
|||
# Web SDK / JS tooling (run from packages/)
|
||||
cd packages && bun run lint # Lint the web SDK (oxlint); also: bun run format
|
||||
cd packages && bun run generate-iconify-catalog # Regenerate the Rust icon catalog assets
|
||||
cd packages && bun run sync-version # Sync SDK versions from root Cargo.toml
|
||||
cd packages && bun run sync-version:check # Verify SDK versions match root Cargo.toml
|
||||
scripts/sync-version.sh # Sync all managed versions from root Cargo.toml
|
||||
tools/check-version-sync.sh # Verify all managed versions match root Cargo.toml
|
||||
```
|
||||
|
||||
## 기여하기
|
||||
|
|
|
|||
|
|
@ -479,7 +479,7 @@ openpencil/
|
|||
│ ├── jian/ GPU-Skia UI framework — widgets/render/events
|
||||
│ ├── casement/ winit fork
|
||||
│ └── agent/ Cross-product Rust agent runtime (agent-rs)
|
||||
└── .githooks/ Pre-commit version sync from branch name
|
||||
└── .githooks/ Pre-commit version consistency check
|
||||
```
|
||||
|
||||
## Keyboard Shortcuts
|
||||
|
|
@ -516,8 +516,8 @@ cargo run -p op-cli -- <args> # CLI (binary: op)
|
|||
# Web SDK / JS tooling (run from packages/)
|
||||
cd packages && bun run lint # Lint the web SDK (oxlint); also: bun run format
|
||||
cd packages && bun run generate-iconify-catalog # Regenerate the Rust icon catalog assets
|
||||
cd packages && bun run sync-version # Sync SDK versions from root Cargo.toml
|
||||
cd packages && bun run sync-version:check # Verify SDK versions match root Cargo.toml
|
||||
scripts/sync-version.sh # Sync all managed versions from root Cargo.toml
|
||||
tools/check-version-sync.sh # Verify all managed versions match root Cargo.toml
|
||||
```
|
||||
|
||||
### Rust workspace details
|
||||
|
|
|
|||
|
|
@ -341,7 +341,7 @@ openpencil/
|
|||
│ ├── jian/ Framework de UI GPU-Skia — widgets/renderização/eventos
|
||||
│ ├── casement/ Fork do winit
|
||||
│ └── agent/ Runtime de agente Rust compartilhado entre produtos (agent-rs)
|
||||
└── .githooks/ Sincronização de versão no pre-commit a partir do nome da branch
|
||||
└── .githooks/ Verificação de consistência de versão no pre-commit
|
||||
```
|
||||
|
||||
## Atalhos de Teclado
|
||||
|
|
@ -378,8 +378,8 @@ cargo run -p op-cli -- <args> # CLI (binary: op)
|
|||
# Web SDK / JS tooling (run from packages/)
|
||||
cd packages && bun run lint # Lint the web SDK (oxlint); also: bun run format
|
||||
cd packages && bun run generate-iconify-catalog # Regenerate the Rust icon catalog assets
|
||||
cd packages && bun run sync-version # Sync SDK versions from root Cargo.toml
|
||||
cd packages && bun run sync-version:check # Verify SDK versions match root Cargo.toml
|
||||
scripts/sync-version.sh # Sync all managed versions from root Cargo.toml
|
||||
tools/check-version-sync.sh # Verify all managed versions match root Cargo.toml
|
||||
```
|
||||
|
||||
## Contribuindo
|
||||
|
|
|
|||
|
|
@ -378,8 +378,8 @@ cargo run -p op-cli -- <args> # CLI (binary: op)
|
|||
# Web SDK / JS tooling (run from packages/)
|
||||
cd packages && bun run lint # Lint the web SDK (oxlint); also: bun run format
|
||||
cd packages && bun run generate-iconify-catalog # Regenerate the Rust icon catalog assets
|
||||
cd packages && bun run sync-version # Sync SDK versions from root Cargo.toml
|
||||
cd packages && bun run sync-version:check # Verify SDK versions match root Cargo.toml
|
||||
scripts/sync-version.sh # Sync all managed versions from root Cargo.toml
|
||||
tools/check-version-sync.sh # Verify all managed versions match root Cargo.toml
|
||||
```
|
||||
|
||||
## Участие в разработке
|
||||
|
|
|
|||
|
|
@ -341,7 +341,7 @@ openpencil/
|
|||
│ ├── jian/ เฟรมเวิร์ก UI แบบ GPU-Skia — widget/render/event
|
||||
│ ├── casement/ winit fork
|
||||
│ └── agent/ Rust agent runtime ข้ามผลิตภัณฑ์ (agent-rs)
|
||||
└── .githooks/ Pre-commit version sync จาก branch name
|
||||
└── .githooks/ การตรวจสอบความสอดคล้องของเวอร์ชันก่อน commit
|
||||
```
|
||||
|
||||
## คีย์ลัด
|
||||
|
|
@ -378,8 +378,8 @@ cargo run -p op-cli -- <args> # CLI (binary: op)
|
|||
# Web SDK / JS tooling (run from packages/)
|
||||
cd packages && bun run lint # Lint the web SDK (oxlint); also: bun run format
|
||||
cd packages && bun run generate-iconify-catalog # Regenerate the Rust icon catalog assets
|
||||
cd packages && bun run sync-version # Sync SDK versions from root Cargo.toml
|
||||
cd packages && bun run sync-version:check # Verify SDK versions match root Cargo.toml
|
||||
scripts/sync-version.sh # Sync all managed versions from root Cargo.toml
|
||||
tools/check-version-sync.sh # Verify all managed versions match root Cargo.toml
|
||||
```
|
||||
|
||||
## การมีส่วนร่วม
|
||||
|
|
|
|||
|
|
@ -378,8 +378,8 @@ cargo run -p op-cli -- <args> # CLI (binary: op)
|
|||
# Web SDK / JS tooling (run from packages/)
|
||||
cd packages && bun run lint # Lint the web SDK (oxlint); also: bun run format
|
||||
cd packages && bun run generate-iconify-catalog # Regenerate the Rust icon catalog assets
|
||||
cd packages && bun run sync-version # Sync SDK versions from root Cargo.toml
|
||||
cd packages && bun run sync-version:check # Verify SDK versions match root Cargo.toml
|
||||
scripts/sync-version.sh # Sync all managed versions from root Cargo.toml
|
||||
tools/check-version-sync.sh # Verify all managed versions match root Cargo.toml
|
||||
```
|
||||
|
||||
## Katkıda Bulunma
|
||||
|
|
|
|||
|
|
@ -378,8 +378,8 @@ cargo run -p op-cli -- <args> # CLI (binary: op)
|
|||
# Web SDK / JS tooling (run from packages/)
|
||||
cd packages && bun run lint # Lint the web SDK (oxlint); also: bun run format
|
||||
cd packages && bun run generate-iconify-catalog # Regenerate the Rust icon catalog assets
|
||||
cd packages && bun run sync-version # Sync SDK versions from root Cargo.toml
|
||||
cd packages && bun run sync-version:check # Verify SDK versions match root Cargo.toml
|
||||
scripts/sync-version.sh # Sync all managed versions from root Cargo.toml
|
||||
tools/check-version-sync.sh # Verify all managed versions match root Cargo.toml
|
||||
```
|
||||
|
||||
## Đóng góp
|
||||
|
|
|
|||
|
|
@ -378,8 +378,8 @@ cargo run -p op-cli -- <args> # CLI (binary: op)
|
|||
# Web SDK / JS tooling (run from packages/)
|
||||
cd packages && bun run lint # Lint the web SDK (oxlint); also: bun run format
|
||||
cd packages && bun run generate-iconify-catalog # Regenerate the Rust icon catalog assets
|
||||
cd packages && bun run sync-version # Sync SDK versions from root Cargo.toml
|
||||
cd packages && bun run sync-version:check # Verify SDK versions match root Cargo.toml
|
||||
scripts/sync-version.sh # Sync all managed versions from root Cargo.toml
|
||||
tools/check-version-sync.sh # Verify all managed versions match root Cargo.toml
|
||||
```
|
||||
|
||||
## 參與貢獻
|
||||
|
|
|
|||
|
|
@ -378,8 +378,8 @@ cargo run -p op-cli -- <args> # CLI (binary: op)
|
|||
# Web SDK / JS tooling (run from packages/)
|
||||
cd packages && bun run lint # Lint the web SDK (oxlint); also: bun run format
|
||||
cd packages && bun run generate-iconify-catalog # Regenerate the Rust icon catalog assets
|
||||
cd packages && bun run sync-version # Sync SDK versions from root Cargo.toml
|
||||
cd packages && bun run sync-version:check # Verify SDK versions match root Cargo.toml
|
||||
scripts/sync-version.sh # Sync all managed versions from root Cargo.toml
|
||||
tools/check-version-sync.sh # Verify all managed versions match root Cargo.toml
|
||||
```
|
||||
|
||||
## 参与贡献
|
||||
|
|
|
|||
36
scripts/sync-version.sh
Executable file
36
scripts/sync-version.sh
Executable file
|
|
@ -0,0 +1,36 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -eu
|
||||
|
||||
if [ "$#" -ne 0 ]; then
|
||||
printf 'usage: scripts/sync-version.sh\n' >&2
|
||||
printf 'sync-version: edit [workspace.package].version in Cargo.toml, then run this command without arguments\n' >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
script_dir=$(CDPATH= cd "$(dirname "$0")" && pwd)
|
||||
repo_root=$(CDPATH= cd "$script_dir/.." && pwd)
|
||||
|
||||
if ! canonical_version=$("$repo_root/scripts/workspace-version.sh"); then
|
||||
printf 'sync-version: failed to read the canonical Cargo workspace version\n' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
printf 'sync-version: canonical Cargo workspace version is %s\n' "$canonical_version"
|
||||
|
||||
if ! (cd "$repo_root" && cargo metadata --no-deps --format-version 1 >/dev/null); then
|
||||
printf 'sync-version: Cargo lock refresh failed\n' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! (cd "$repo_root/packages" && bun run sync-version); then
|
||||
printf 'sync-version: package version synchronization failed\n' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! (cd "$repo_root" && "$repo_root/tools/check-version-sync.sh"); then
|
||||
printf 'sync-version: version consistency check failed\n' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
printf 'sync-version: all managed versions are synchronized to %s\n' "$canonical_version"
|
||||
209
scripts/sync-version.test.sh
Executable file
209
scripts/sync-version.test.sh
Executable file
|
|
@ -0,0 +1,209 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
script_dir=$(CDPATH= cd "$(dirname "$0")" && pwd)
|
||||
repo_root=$(CDPATH= cd "$script_dir/.." && pwd)
|
||||
sync_source="$script_dir/sync-version.sh"
|
||||
reader_source="$script_dir/workspace-version.sh"
|
||||
tmp_base=${TMPDIR:-/tmp}
|
||||
tmp_dir=$(mktemp -d "${tmp_base%/}/sync-version.XXXXXX")
|
||||
trap 'rm -rf "$tmp_dir"' 0 HUP INT TERM
|
||||
|
||||
test_count=0
|
||||
case_status=0
|
||||
case_output=
|
||||
|
||||
fail() {
|
||||
printf 'not ok %s - %s\n' "$test_count" "$1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
pass() {
|
||||
test_count=$((test_count + 1))
|
||||
printf 'ok %s - %s\n' "$test_count" "$1"
|
||||
}
|
||||
|
||||
assert_status() {
|
||||
expected=$1
|
||||
label=$2
|
||||
if [ "$case_status" -ne "$expected" ]; then
|
||||
printf '%s\n' "$case_output" >&2
|
||||
fail "$label: expected status $expected, got $case_status"
|
||||
fi
|
||||
}
|
||||
|
||||
assert_contains() {
|
||||
needle=$1
|
||||
label=$2
|
||||
case "$case_output" in
|
||||
*"$needle"*) ;;
|
||||
*)
|
||||
printf '%s\n' "$case_output" >&2
|
||||
fail "$label: missing output: $needle"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
assert_file_contains() {
|
||||
file=$1
|
||||
needle=$2
|
||||
label=$3
|
||||
if ! grep -Fq -- "$needle" "$file"; then
|
||||
fail "$label: $file does not contain: $needle"
|
||||
fi
|
||||
}
|
||||
|
||||
assert_file_not_matches() {
|
||||
file=$1
|
||||
pattern=$2
|
||||
label=$3
|
||||
if grep -Eq -- "$pattern" "$file"; then
|
||||
fail "$label: $file unexpectedly matches: $pattern"
|
||||
fi
|
||||
}
|
||||
|
||||
cargo() {
|
||||
printf 'cargo:%s:%s\n' "$PWD" "$*" >> "$SYNC_TEST_LOG"
|
||||
if [ -e "$PWD/.fail-cargo" ]; then
|
||||
printf 'fake cargo failure\n' >&2
|
||||
return 31
|
||||
fi
|
||||
version=$(sed -n 's/^version = "\([^"]*\)"/\1/p' "$PWD/Cargo.toml")
|
||||
printf 'lock-version=%s\n' "$version" > "$PWD/Cargo.lock"
|
||||
printf '%s\n' '{"packages":[]}'
|
||||
}
|
||||
|
||||
bun() {
|
||||
printf 'bun:%s:%s\n' "$PWD" "$*" >> "$SYNC_TEST_LOG"
|
||||
repo_root=$(CDPATH= cd "$(dirname "$PWD")" && pwd)
|
||||
if [ -e "$repo_root/.fail-bun" ]; then
|
||||
printf 'fake bun failure\n' >&2
|
||||
return 32
|
||||
fi
|
||||
version=$(sed -n 's/^version = "\([^"]*\)"/\1/p' "$repo_root/Cargo.toml")
|
||||
printf '{"version":"%s"}\n' "$version" > "$PWD/package.json"
|
||||
}
|
||||
|
||||
export -f cargo bun
|
||||
|
||||
new_repo() {
|
||||
name=$1
|
||||
repo="$tmp_dir/$name"
|
||||
mkdir -p "$repo/scripts" "$repo/tools" "$repo/packages" "$repo/outside"
|
||||
ln -s "$sync_source" "$repo/scripts/sync-version.sh"
|
||||
ln -s "$reader_source" "$repo/scripts/workspace-version.sh"
|
||||
printf '%s\n' \
|
||||
'[workspace]' \
|
||||
'members = []' \
|
||||
'' \
|
||||
'[workspace.package]' \
|
||||
'version = "2.3.4"' > "$repo/Cargo.toml"
|
||||
printf '%s\n' 'lock-version=1.0.0' > "$repo/Cargo.lock"
|
||||
printf '%s\n' '{"version":"1.0.0"}' > "$repo/packages/package.json"
|
||||
|
||||
cat > "$repo/tools/check-version-sync.sh" <<'SCRIPT'
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
repo_root=$(CDPATH= cd "$(dirname "$0")/.." && pwd)
|
||||
printf 'guard:%s\n' "$PWD" >> "$SYNC_TEST_LOG"
|
||||
if [ -e "$repo_root/.fail-guard" ]; then
|
||||
printf 'fake guard failure\n' >&2
|
||||
exit 33
|
||||
fi
|
||||
SCRIPT
|
||||
chmod +x "$repo/tools/check-version-sync.sh"
|
||||
printf '%s\n' "$repo"
|
||||
}
|
||||
|
||||
run_sync() {
|
||||
repo=$1
|
||||
shift
|
||||
case_status=0
|
||||
case_output=$(cd "$repo/outside" && env SYNC_TEST_LOG="$repo/calls.log" \
|
||||
bash "$repo/scripts/sync-version.sh" "$@" 2>&1) || case_status=$?
|
||||
}
|
||||
|
||||
case_status=0
|
||||
case_output=$("$sync_source" 2.3.4 2>&1) || case_status=$?
|
||||
assert_status 2 'argument rejection'
|
||||
assert_contains 'usage: scripts/sync-version.sh' 'argument rejection'
|
||||
pass 'sync entrypoint rejects positional versions with actionable usage'
|
||||
|
||||
repo=$(new_repo external_cwd)
|
||||
run_sync "$repo"
|
||||
assert_status 0 'external cwd'
|
||||
assert_file_contains "$repo/calls.log" "cargo:$repo:metadata --no-deps --format-version 1" \
|
||||
'external cwd'
|
||||
assert_file_contains "$repo/calls.log" "bun:$repo/packages:run sync-version" 'external cwd'
|
||||
assert_file_contains "$repo/calls.log" "guard:$repo" 'external cwd'
|
||||
assert_file_contains "$repo/Cargo.lock" 'lock-version=2.3.4' 'external cwd'
|
||||
assert_file_contains "$repo/packages/package.json" '"version":"2.3.4"' 'external cwd'
|
||||
pass 'sync entrypoint locates the repository and runs every stage from an external cwd'
|
||||
|
||||
first_hash=$(shasum "$repo/Cargo.lock" "$repo/packages/package.json")
|
||||
run_sync "$repo"
|
||||
assert_status 0 'idempotent rerun'
|
||||
second_hash=$(shasum "$repo/Cargo.lock" "$repo/packages/package.json")
|
||||
if [ "$first_hash" != "$second_hash" ]; then
|
||||
fail 'idempotent rerun changed managed file hashes'
|
||||
fi
|
||||
pass 'running synchronization twice leaves managed file hashes unchanged'
|
||||
|
||||
repo=$(new_repo cargo_failure)
|
||||
touch "$repo/.fail-cargo"
|
||||
run_sync "$repo"
|
||||
assert_status 1 'Cargo stage failure'
|
||||
assert_contains 'sync-version: Cargo lock refresh failed' 'Cargo stage failure'
|
||||
pass 'Cargo refresh failures identify the failing synchronization stage'
|
||||
|
||||
repo=$(new_repo bun_failure)
|
||||
touch "$repo/.fail-bun"
|
||||
run_sync "$repo"
|
||||
assert_status 1 'package stage failure'
|
||||
assert_contains 'sync-version: package version synchronization failed' 'package stage failure'
|
||||
pass 'package synchronization failures identify the failing stage'
|
||||
|
||||
repo=$(new_repo guard_failure)
|
||||
touch "$repo/.fail-guard"
|
||||
run_sync "$repo"
|
||||
assert_status 1 'guard stage failure'
|
||||
assert_contains 'sync-version: version consistency check failed' 'guard stage failure'
|
||||
pass 'guard failures identify the final verification stage'
|
||||
|
||||
hook="$repo_root/.githooks/pre-commit"
|
||||
assert_file_contains "$hook" 'tools/check-version-sync.sh' 'pre-commit guard'
|
||||
assert_file_not_matches "$hook" 'rev-parse --abbrev-ref|grep -oE.*[0-9]|git add|jq --arg|\.tmp.*mv' \
|
||||
'pre-commit detect-only policy'
|
||||
guard_line=$(grep -n 'tools/check-version-sync.sh' "$hook" | head -n 1 | cut -d: -f1)
|
||||
fmt_line=$(grep -n 'cargo fmt' "$hook" | head -n 1 | cut -d: -f1)
|
||||
if [ -z "$guard_line" ] || [ -z "$fmt_line" ] || [ "$guard_line" -ge "$fmt_line" ]; then
|
||||
fail 'pre-commit guard must run before Rust format and lint checks'
|
||||
fi
|
||||
pass 'pre-commit is detect-only and runs the version guard before Rust checks'
|
||||
|
||||
workflow="$repo_root/.github/workflows/version-sync.yml"
|
||||
assert_file_contains "$workflow" 'pull_request:' 'version sync workflow trigger'
|
||||
assert_file_contains "$workflow" 'push:' 'version sync workflow trigger'
|
||||
assert_file_contains "$workflow" 'submodules: recursive' 'version sync checkout'
|
||||
assert_file_contains "$workflow" 'dtolnay/rust-toolchain@stable' 'version sync Rust setup'
|
||||
assert_file_contains "$workflow" 'oven-sh/setup-bun@v2' 'version sync Bun setup'
|
||||
assert_file_contains "$workflow" 'bun install --frozen-lockfile' 'version sync dependency install'
|
||||
assert_file_contains "$workflow" 'packages/bun.lock' 'version sync managed paths'
|
||||
assert_file_contains "$workflow" 'packages/scripts/sync-version.mjs' 'version sync implementation paths'
|
||||
assert_file_not_matches "$workflow" 'packages/\*\*' 'version sync focused path filters'
|
||||
assert_file_contains "$workflow" 'scripts/workspace-version.test.sh' 'version reader tests'
|
||||
assert_file_contains "$workflow" 'scripts/sync-version.test.sh' 'version sync tests'
|
||||
assert_file_contains "$workflow" 'tools/check-version-sync.test.sh' 'version guard tests'
|
||||
assert_file_contains "$workflow" 'tools/check-version-sync.sh' 'version guard'
|
||||
pass 'dedicated CI installs prerequisites and runs the focused version checks'
|
||||
|
||||
old_guard_name='check-version-'"fixtures"
|
||||
if rg -n "$old_guard_name" "$repo_root" --hidden \
|
||||
--glob '!.git/**' --glob '!vendor/**' > "$tmp_dir/old-paths"; then
|
||||
sed 's/^/ /' "$tmp_dir/old-paths" >&2
|
||||
fail 'old version guard paths remain in the repository'
|
||||
fi
|
||||
pass 'repository no longer references the retired fixture-only guard name'
|
||||
|
||||
printf '1..%s\n' "$test_count"
|
||||
|
|
@ -5,6 +5,14 @@ set -euo pipefail
|
|||
script_dir=$(CDPATH= cd "$(dirname "$0")" && pwd)
|
||||
repo_root=$(CDPATH= cd "$script_dir/.." && pwd)
|
||||
fixture_version=1.0.0
|
||||
|
||||
for required_command in cargo jq bun rg; do
|
||||
if ! command -v "$required_command" >/dev/null 2>&1; then
|
||||
printf 'version-sync: required command not found: %s\n' "$required_command" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
current_version=$(bash "$repo_root/scripts/workspace-version.sh")
|
||||
|
||||
cd "$repo_root"
|
||||
|
|
@ -170,8 +178,110 @@ reject_matches() {
|
|||
fi
|
||||
}
|
||||
|
||||
validate_workspace_package_versions() {
|
||||
if ! metadata=$(cargo metadata --no-deps --format-version 1 --locked); then
|
||||
report_missing Cargo.lock \
|
||||
'cargo metadata --locked failed; run scripts/sync-version.sh to refresh the lockfile'
|
||||
return
|
||||
fi
|
||||
|
||||
mismatch_status=0
|
||||
mismatches=$(printf '%s\n' "$metadata" | jq -r \
|
||||
--arg crates_prefix "$repo_root/crates/" \
|
||||
--arg expected "$current_version" '
|
||||
.packages[]?
|
||||
| select(.name | startswith("op-"))
|
||||
| select(.manifest_path | startswith($crates_prefix))
|
||||
| select(.version != $expected)
|
||||
| [.manifest_path, .name, .version]
|
||||
| @tsv
|
||||
' 2>&1) || mismatch_status=$?
|
||||
if [[ "$mismatch_status" -ne 0 ]]; then
|
||||
printf '%s\n' "$mismatches" >&2
|
||||
report_missing Cargo.toml 'failed to inspect cargo metadata with jq'
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ -n "$mismatches" ]]; then
|
||||
while IFS=$'\t' read -r manifest package package_version; do
|
||||
relative_manifest=${manifest#"$repo_root"/}
|
||||
printf '%s:1: error: workspace package %s has version %s; expected %s\n' \
|
||||
"$relative_manifest" "$package" "$package_version" "$current_version" >&2
|
||||
errors=1
|
||||
done <<< "$mismatches"
|
||||
fi
|
||||
}
|
||||
|
||||
validate_package_versions() {
|
||||
package_status=0
|
||||
package_output=$(cd packages && bun run sync-version:check 2>&1) || package_status=$?
|
||||
if [[ "$package_status" -ne 0 ]]; then
|
||||
printf '%s\n' "$package_output" >&2
|
||||
report_missing packages \
|
||||
'bun run sync-version:check failed; run scripts/sync-version.sh to repair package drift'
|
||||
fi
|
||||
}
|
||||
|
||||
validate_release_tag() {
|
||||
tag_name=
|
||||
if [[ "${GITHUB_REF:-}" == refs/tags/v* ]]; then
|
||||
tag_name=${GITHUB_REF#refs/tags/}
|
||||
elif [[ -z "${GITHUB_REF:-}" && "${GITHUB_REF_NAME:-}" == v* ]]; then
|
||||
tag_name=$GITHUB_REF_NAME
|
||||
fi
|
||||
|
||||
if [[ -n "$tag_name" && "${tag_name#v}" != "$current_version" ]]; then
|
||||
report_missing environment \
|
||||
"release tag ${tag_name} does not match Cargo workspace version ${current_version}"
|
||||
fi
|
||||
}
|
||||
|
||||
validate_cli_bundle_version_template() {
|
||||
bundle=crates/op-cli/assets/skill-bundle.json
|
||||
sentinel=__OPENPENCIL_VERSION__
|
||||
sentinel_count=$(rg --fixed-strings --count-matches -- "$sentinel" "$bundle" || true)
|
||||
if [[ "${sentinel_count:-0}" != 6 ]]; then
|
||||
report_missing "$bundle" \
|
||||
"expected exactly 6 version sentinels ${sentinel} (found ${sentinel_count:-0})"
|
||||
fi
|
||||
reject_matches fixed "$bundle" "$current_version" \
|
||||
'embedded CLI bundle must not contain the canonical version literal'
|
||||
}
|
||||
|
||||
validate_rust_product_version_producers() {
|
||||
require_statement crates/op-editor-core/src/state.rs \
|
||||
'version:[[:space:]]*env!\("CARGO_PKG_VERSION"\)[.]to_owned\(\),' \
|
||||
'empty documents must derive their version from CARGO_PKG_VERSION'
|
||||
|
||||
host_support=crates/op-editor-core/src/host_support.rs
|
||||
host_version_count=$(rg --fixed-strings --count-matches -- \
|
||||
'src.replace("__OPENPENCIL_VERSION__", env!("CARGO_PKG_VERSION"))' \
|
||||
"$host_support" || true)
|
||||
if [[ "$host_version_count" != 3 ]]; then
|
||||
report_missing "$host_support" \
|
||||
"expected 3 document templates to derive from CARGO_PKG_VERSION (found ${host_version_count:-0})"
|
||||
fi
|
||||
|
||||
cli_source=crates/op-cli/src/app_control_cli.rs
|
||||
require_regex "$cli_source" 'env!\("CARGO_PKG_VERSION"\)' \
|
||||
'CLI starter documents must derive their version from CARGO_PKG_VERSION'
|
||||
reject_matches regex "$cli_source" \
|
||||
'"version"[^[:cntrl:]]*"[0-9]+[.][0-9]+[.][0-9]+' \
|
||||
'CLI starter documents must not hard-code a product version'
|
||||
|
||||
reject_matches regex crates/op-host-desktop/Cargo.toml \
|
||||
'^[[:space:]]*op-host-native[[:space:]]*=.*path[[:space:]]*=.*version[[:space:]]*=' \
|
||||
'local op-host-native dependency must not duplicate the product version'
|
||||
}
|
||||
|
||||
validate_workspace_package_versions
|
||||
validate_package_versions
|
||||
validate_release_tag
|
||||
validate_cli_bundle_version_template
|
||||
validate_rust_product_version_producers
|
||||
|
||||
if [[ "$current_version" == "$fixture_version" ]]; then
|
||||
printf 'version-fixtures: current product version %s equals stable fixture version %s; skipping literal fixture drift scan because stable fixtures and product-version literals are indistinguishable\n' \
|
||||
printf 'version-sync: current product version %s equals stable fixture version %s; skipping literal fixture drift scan because stable fixtures and product-version literals are indistinguishable\n' \
|
||||
"$current_version" "$fixture_version"
|
||||
fixture_scan_skipped=1
|
||||
else
|
||||
|
|
@ -187,15 +297,15 @@ else
|
|||
crates) || rg_status=$?
|
||||
|
||||
if [[ "$rg_status" -gt 1 ]]; then
|
||||
printf 'version-fixtures: failed to scan Rust sources with rg (status %s)\n' "$rg_status" >&2
|
||||
printf 'version-sync: failed to scan Rust sources with rg (status %s)\n' "$rg_status" >&2
|
||||
exit "$rg_status"
|
||||
fi
|
||||
|
||||
if [[ -n "$matches" ]]; then
|
||||
printf 'version-fixtures: ordinary Rust fixtures copy current product version %s:\n' \
|
||||
printf 'version-sync: ordinary Rust fixtures copy current product version %s:\n' \
|
||||
"$current_version" >&2
|
||||
printf '%s\n' "$matches" >&2
|
||||
printf 'version-fixtures: use stable %s test data unless a test explicitly covers compatibility, migration, or updates\n' \
|
||||
printf 'version-sync: use stable %s test data unless a test explicitly covers compatibility, migration, or updates\n' \
|
||||
"$fixture_version" >&2
|
||||
errors=1
|
||||
fi
|
||||
|
|
@ -319,8 +429,8 @@ if [[ "$errors" -ne 0 ]]; then
|
|||
fi
|
||||
|
||||
if [[ "$fixture_scan_skipped" -eq 0 ]]; then
|
||||
printf 'version-fixtures: no ordinary Rust fixtures copy current product version %s\n' \
|
||||
printf 'version-sync: no ordinary Rust fixtures copy current product version %s\n' \
|
||||
"$current_version"
|
||||
fi
|
||||
printf 'version-fixtures: packaging and release versions derive from Cargo workspace version %s\n' \
|
||||
printf 'version-sync: all managed versions derive from Cargo workspace version %s\n' \
|
||||
"$current_version"
|
||||
|
|
@ -3,9 +3,9 @@
|
|||
set -euo pipefail
|
||||
|
||||
script_dir=$(CDPATH= cd "$(dirname "$0")" && pwd)
|
||||
guard_source="$script_dir/check-version-fixtures.sh"
|
||||
guard_source="$script_dir/check-version-sync.sh"
|
||||
reader_source="$script_dir/../scripts/workspace-version.sh"
|
||||
temp_root=$(mktemp -d "${TMPDIR:-/tmp}/check-version-fixtures.XXXXXX")
|
||||
temp_root=$(mktemp -d "${TMPDIR:-/tmp}/check-version-sync.XXXXXX")
|
||||
trap 'rm -rf "$temp_root"' EXIT HUP INT TERM
|
||||
|
||||
tests_run=0
|
||||
|
|
@ -61,6 +61,38 @@ assert_no_success_output() {
|
|||
assert_not_contains 'skipping literal fixture drift scan' "$label"
|
||||
}
|
||||
|
||||
cargo() {
|
||||
if [[ "$*" != 'metadata --no-deps --format-version 1 --locked' ]]; then
|
||||
printf 'unexpected cargo arguments: %s\n' "$*" >&2
|
||||
return 41
|
||||
fi
|
||||
repo_root=$PWD
|
||||
canonical=$("$repo_root/scripts/workspace-version.sh")
|
||||
package_version=$canonical
|
||||
if [[ -f "$repo_root/.fake-cargo-version" ]]; then
|
||||
package_version=$(sed -n '1p' "$repo_root/.fake-cargo-version")
|
||||
fi
|
||||
if [[ -e "$repo_root/.fake-cargo-warning" ]]; then
|
||||
printf 'warning: fake Cargo metadata warning\n' >&2
|
||||
fi
|
||||
printf '{"packages":[{"name":"op-example","version":"%s","manifest_path":"%s/crates/example/Cargo.toml"}]}\n' \
|
||||
"$package_version" "$repo_root"
|
||||
}
|
||||
|
||||
bun() {
|
||||
repo_root=$(CDPATH= cd "$PWD/.." && pwd)
|
||||
if [[ "$PWD" != "$repo_root/packages" || "$*" != 'run sync-version:check' ]]; then
|
||||
printf 'unexpected bun invocation: cwd=%s args=%s\n' "$PWD" "$*" >&2
|
||||
return 42
|
||||
fi
|
||||
if [[ -e "$repo_root/.fake-bun-fail" ]]; then
|
||||
printf 'package versions are stale\n' >&2
|
||||
return 43
|
||||
fi
|
||||
}
|
||||
|
||||
export -f cargo bun
|
||||
|
||||
write_workflow_fixture() {
|
||||
repo=$1
|
||||
dependency_mode=$2
|
||||
|
|
@ -158,14 +190,19 @@ new_repo() {
|
|||
|
||||
mkdir -p \
|
||||
"$repo/.github/workflows" \
|
||||
"$repo/packages" \
|
||||
"$repo/tools" \
|
||||
"$repo/scripts" \
|
||||
"$repo/crates/op-cli/assets" \
|
||||
"$repo/crates/op-cli/src" \
|
||||
"$repo/crates/op-editor-core/src" \
|
||||
"$repo/crates/op-host-desktop" \
|
||||
"$repo/crates/example/src" \
|
||||
"$repo/crates/op-host-desktop/src"
|
||||
git -C "$repo" init -q
|
||||
cp "$guard_source" "$repo/tools/check-version-fixtures.sh"
|
||||
cp "$guard_source" "$repo/tools/check-version-sync.sh"
|
||||
cp "$reader_source" "$repo/scripts/workspace-version.sh"
|
||||
chmod +x "$repo/tools/check-version-fixtures.sh" "$repo/scripts/workspace-version.sh"
|
||||
chmod +x "$repo/tools/check-version-sync.sh" "$repo/scripts/workspace-version.sh"
|
||||
printf '%s\n' \
|
||||
'[workspace]' \
|
||||
'members = []' \
|
||||
|
|
@ -173,6 +210,26 @@ new_repo() {
|
|||
'[workspace.package]' \
|
||||
"version = \"$version\"" \
|
||||
'edition = "2024"' > "$repo/Cargo.toml"
|
||||
printf '%s\n' 'version = 4' > "$repo/Cargo.lock"
|
||||
printf '%s\n' '{"name":"fixture-packages"}' > "$repo/packages/package.json"
|
||||
|
||||
cat > "$repo/crates/op-cli/assets/skill-bundle.json" <<'JSON'
|
||||
{"one":"__OPENPENCIL_VERSION__","two":"__OPENPENCIL_VERSION__","three":"__OPENPENCIL_VERSION__","four":"__OPENPENCIL_VERSION__","five":"__OPENPENCIL_VERSION__","six":"__OPENPENCIL_VERSION__"}
|
||||
JSON
|
||||
cat > "$repo/crates/op-editor-core/src/state.rs" <<'RUST'
|
||||
version: env!("CARGO_PKG_VERSION").to_owned(),
|
||||
RUST
|
||||
cat > "$repo/crates/op-editor-core/src/host_support.rs" <<'RUST'
|
||||
let src = src.replace("__OPENPENCIL_VERSION__", env!("CARGO_PKG_VERSION"));
|
||||
let src = src.replace("__OPENPENCIL_VERSION__", env!("CARGO_PKG_VERSION"));
|
||||
let src = src.replace("__OPENPENCIL_VERSION__", env!("CARGO_PKG_VERSION"));
|
||||
RUST
|
||||
cat > "$repo/crates/op-cli/src/app_control_cli.rs" <<'RUST'
|
||||
const MINIMAL_DOCUMENT: &str = concat!(env!("CARGO_PKG_VERSION"));
|
||||
RUST
|
||||
cat > "$repo/crates/op-host-desktop/Cargo.toml" <<'TOML'
|
||||
op-host-native = { path = "../op-host-native", features = ["gl-host"] }
|
||||
TOML
|
||||
|
||||
cat > "$repo/scripts/bundle-macos.sh" <<'SCRIPT'
|
||||
#!/usr/bin/env bash
|
||||
|
|
@ -229,8 +286,18 @@ SCRIPT
|
|||
|
||||
run_guard() {
|
||||
repo=$1
|
||||
shift
|
||||
case_status=0
|
||||
case_output=$(cd "$repo" && bash tools/check-version-fixtures.sh 2>&1) || case_status=$?
|
||||
case_output=$(cd "$repo" && env "$@" \
|
||||
bash tools/check-version-sync.sh 2>&1) || case_status=$?
|
||||
}
|
||||
|
||||
repo_snapshot() {
|
||||
repo=$1
|
||||
find "$repo" -type f ! -path "$repo/.git/*" -exec shasum {} + |
|
||||
LC_ALL=C sort |
|
||||
shasum |
|
||||
awk '{print $1}'
|
||||
}
|
||||
|
||||
repo=$(new_repo v_prefixed_stale_version 0.8.1)
|
||||
|
|
@ -470,14 +537,14 @@ printf '%s\n' '# identifier build0.8.2candidate is not a version token' \
|
|||
>> "$repo/scripts/install-op.sh"
|
||||
run_guard "$repo"
|
||||
assert_status 0 'embedded version-like substring'
|
||||
assert_contains 'packaging and release versions derive from Cargo workspace version 0.8.1' \
|
||||
assert_contains 'all managed versions derive from Cargo workspace version 0.8.1' \
|
||||
'embedded version-like substring'
|
||||
pass 'version-like substrings inside larger identifiers are allowed'
|
||||
|
||||
repo=$(new_repo nsis_defensive_fallback 0.8.1)
|
||||
run_guard "$repo"
|
||||
assert_status 0 'NSIS defensive fallback'
|
||||
assert_contains 'packaging and release versions derive from Cargo workspace version 0.8.1' \
|
||||
assert_contains 'all managed versions derive from Cargo workspace version 0.8.1' \
|
||||
'NSIS defensive fallback'
|
||||
pass 'NSIS 0.0.0 defensive fallback remains allowed'
|
||||
|
||||
|
|
@ -518,4 +585,104 @@ assert_not_contains 'no ordinary Rust fixtures copy current product version' \
|
|||
'fixture-version collision packaging check'
|
||||
pass 'fixture-version collision still runs packaging checks'
|
||||
|
||||
repo=$(new_repo cargo_metadata_version_mismatch 0.8.1)
|
||||
printf '%s\n' '0.8.0' > "$repo/.fake-cargo-version"
|
||||
run_guard "$repo"
|
||||
assert_status 1 'Cargo metadata version mismatch'
|
||||
assert_contains 'crates/example/Cargo.toml:1: error: workspace package op-example has version 0.8.0; expected 0.8.1' \
|
||||
'Cargo metadata version mismatch'
|
||||
assert_no_success_output 'Cargo metadata version mismatch'
|
||||
pass 'workspace op-* packages under crates must match the canonical Cargo version'
|
||||
|
||||
repo=$(new_repo cargo_metadata_warning 0.8.1)
|
||||
touch "$repo/.fake-cargo-warning"
|
||||
run_guard "$repo"
|
||||
assert_status 0 'Cargo metadata warning'
|
||||
assert_contains 'warning: fake Cargo metadata warning' 'Cargo metadata warning'
|
||||
pass 'Cargo warnings do not corrupt the metadata JSON passed to jq'
|
||||
|
||||
repo=$(new_repo package_version_drift 0.8.1)
|
||||
touch "$repo/.fake-bun-fail"
|
||||
run_guard "$repo"
|
||||
assert_status 1 'package version drift'
|
||||
assert_contains 'packages:1: error: bun run sync-version:check failed' 'package version drift'
|
||||
assert_no_success_output 'package version drift'
|
||||
pass 'web SDK package drift is reported by the read-only guard'
|
||||
|
||||
repo=$(new_repo matching_release_tag 0.8.1)
|
||||
run_guard "$repo" GITHUB_REF=refs/tags/v0.8.1 GITHUB_REF_NAME=v0.8.1
|
||||
assert_status 0 'matching release tag'
|
||||
pass 'matching v* release tags pass the repository guard'
|
||||
|
||||
repo=$(new_repo mismatched_release_tag 0.8.1)
|
||||
run_guard "$repo" GITHUB_REF=refs/tags/v0.8.2 GITHUB_REF_NAME=v0.8.2
|
||||
assert_status 1 'mismatched release tag'
|
||||
assert_contains 'environment:1: error: release tag v0.8.2 does not match Cargo workspace version 0.8.1' \
|
||||
'mismatched release tag'
|
||||
assert_no_success_output 'mismatched release tag'
|
||||
pass 'mismatched v* release tags are rejected outside the release workflow too'
|
||||
|
||||
repo=$(new_repo cli_bundle_wrong_sentinel_count 0.8.1)
|
||||
sed -i.bak 's/,"six":"__OPENPENCIL_VERSION__"//' \
|
||||
"$repo/crates/op-cli/assets/skill-bundle.json"
|
||||
rm "$repo/crates/op-cli/assets/skill-bundle.json.bak"
|
||||
run_guard "$repo"
|
||||
assert_status 1 'CLI bundle sentinel count'
|
||||
assert_contains 'crates/op-cli/assets/skill-bundle.json:1: error: expected exactly 6 version sentinels' \
|
||||
'CLI bundle sentinel count'
|
||||
assert_no_success_output 'CLI bundle sentinel count'
|
||||
pass 'embedded CLI bundle retains exactly six version sentinels'
|
||||
|
||||
repo=$(new_repo cli_bundle_without_sentinels 0.8.1)
|
||||
sed -i.bak 's/__OPENPENCIL_VERSION__/__MISSING_VERSION__/g' \
|
||||
"$repo/crates/op-cli/assets/skill-bundle.json"
|
||||
rm "$repo/crates/op-cli/assets/skill-bundle.json.bak"
|
||||
run_guard "$repo"
|
||||
assert_status 1 'CLI bundle missing sentinels'
|
||||
assert_contains 'crates/op-cli/assets/skill-bundle.json:1: error: expected exactly 6 version sentinels' \
|
||||
'CLI bundle missing sentinels'
|
||||
assert_contains '(found 0)' 'CLI bundle missing sentinels'
|
||||
assert_no_success_output 'CLI bundle missing sentinels'
|
||||
pass 'embedded CLI bundle reports zero missing version sentinels actionably'
|
||||
|
||||
repo=$(new_repo cli_bundle_numeric_product_version 0.8.1)
|
||||
printf '%s\n' '{"stale":"0.8.1"}' >> "$repo/crates/op-cli/assets/skill-bundle.json"
|
||||
run_guard "$repo"
|
||||
assert_status 1 'CLI bundle numeric product version'
|
||||
assert_contains 'crates/op-cli/assets/skill-bundle.json:' 'CLI bundle numeric product version'
|
||||
assert_contains 'error: embedded CLI bundle must not contain the canonical version literal' \
|
||||
'CLI bundle numeric product version'
|
||||
assert_no_success_output 'CLI bundle numeric product version'
|
||||
pass 'embedded CLI bundle cannot duplicate the numeric product version'
|
||||
|
||||
repo=$(new_repo hardcoded_rust_product_version 0.8.1)
|
||||
printf '%s\n' 'version: "0.8.1".to_owned(),' > "$repo/crates/op-editor-core/src/state.rs"
|
||||
run_guard "$repo"
|
||||
assert_status 1 'hardcoded Rust product version'
|
||||
assert_contains 'crates/op-editor-core/src/state.rs:1: error: empty documents must derive their version from CARGO_PKG_VERSION' \
|
||||
'hardcoded Rust product version'
|
||||
assert_no_success_output 'hardcoded Rust product version'
|
||||
pass 'Rust product-version producers remain derived from Cargo metadata'
|
||||
|
||||
repo=$(new_repo versioned_local_product_dependency 0.8.1)
|
||||
printf '%s\n' \
|
||||
'op-host-native = { path = "../op-host-native", version = "0.8.1", features = ["gl-host"] }' \
|
||||
> "$repo/crates/op-host-desktop/Cargo.toml"
|
||||
run_guard "$repo"
|
||||
assert_status 1 'versioned local product dependency'
|
||||
assert_contains 'crates/op-host-desktop/Cargo.toml:1: error: local op-host-native dependency must not duplicate the product version' \
|
||||
'versioned local product dependency'
|
||||
assert_no_success_output 'versioned local product dependency'
|
||||
pass 'local product dependencies do not repeat the workspace version'
|
||||
|
||||
repo=$(new_repo guard_is_read_only 0.8.1)
|
||||
before_snapshot=$(repo_snapshot "$repo")
|
||||
run_guard "$repo"
|
||||
assert_status 0 'read-only guard'
|
||||
after_snapshot=$(repo_snapshot "$repo")
|
||||
if [[ "$before_snapshot" != "$after_snapshot" ]]; then
|
||||
fail 'read-only guard changed repository file contents'
|
||||
fi
|
||||
pass 'repository-wide version guard does not write files'
|
||||
|
||||
printf '1..%s\n' "$tests_run"
|
||||
Loading…
Reference in a new issue