Files
easyai/scripts/test-deployment-release-resolution.py
T

67 lines
4.7 KiB
Python

#!/usr/bin/env python3
"""Cross-shell release behavior: stable defaults, independent versions, legacy compatibility."""
import json
import os
from pathlib import Path
import subprocess
import tempfile
root = Path(__file__).resolve().parent.parent
cases = [
('new install', 'VERSION=latest\n', {}, True),
('legacy latest', 'VERSION=latest\nMODEL_CONVERSION_WORKER_VERSION=latest\n', {}, True),
('watchtower aliases', 'VERSION=latest\nSYSTEM_UPDATE_MODE=legacy_watchtower\n', {}, True),
('watchtower variant', 'VERSION=latest-no-ssr\nSYSTEM_UPDATE_MODE=legacy_watchtower\n', {}, True),
('legacy pinned', 'VERSION=3.29.0.20261014.2\n', {}, True),
('recorded product', 'VERSION=latest\n', {'UPDATE_RELEASE_VERSION': '3.29.0.20261014.2'}, True),
('selected server', 'VERSION=latest\n', {'UPDATE_SERVICES': 'easyai-server', 'UPDATE_SERVER_VERSION': '3.29.0.20261014.2'}, True),
('web variant', 'VERSION=latest-no-ssr\n', {}, True),
('updater independent semver', 'VERSION=latest\n', {'UPDATE_SERVICES': 'easyai-updater', 'UPDATE_UPDATER_VERSION': '1.1.0'}, True),
('unknown product', 'VERSION=latest\n', {'UPDATE_RELEASE_VERSION': '9.9.9.20990101'}, False),
('invalid product path', 'VERSION=latest\n', {'UPDATE_RELEASE_VERSION': '../latest'}, False),
('invalid scope', 'VERSION=latest\n', {'UPDATE_SERVICES': 'easyai-server', 'UPDATE_WEB_VERSION': '3.29.0.20261014.2'}, False),
('floating component rejected', 'VERSION=latest\n', {'UPDATE_WEB_VERSION': 'latest'}, False),
]
with tempfile.TemporaryDirectory(prefix='easyai-release-resolution-') as temporary:
path = Path(temporary) / '.env'
for name, content, options, succeeds in cases:
path.write_text(content + 'UPDATE_MANIFEST_SOURCE=local\nCONFIG_JWT_SECRET=private-fixture-must-not-be-printed\n')
before = path.read_bytes()
env = {k: v for k, v in os.environ.items() if not k.startswith(('UPDATE_', 'DEPLOY_'))}
env.update(options)
bash = ['python3', str(root / 'scripts/resolve-deployment-release.py'), '--env-file', str(path), '--format', 'json']
ps = ['pwsh', '-NoProfile', '-NonInteractive', '-Command',
'. $args[0]; . $args[1]; @(Get-ApplicationVersionPlan -Path $args[2]) | ConvertTo-Json -Compress',
str(root / 'scripts/Initialize-SecurityEnv.ps1'), str(root / 'scripts/Initialize-ApplicationVersions.ps1'), str(path)]
# -Command positional arguments are parsed as PowerShell expressions;
# use a saved script to preserve paths with spaces on both shells.
script = Path(temporary) / 'plan.ps1'
script.write_text('param($Security,$Versions,$Path)\n$ErrorActionPreference="Stop"\n. $Security\n. $Versions\n@(Get-ApplicationVersionPlan -Path $Path) | ConvertTo-Json -Compress\n')
ps = ['pwsh', '-NoProfile', '-NonInteractive', '-File', str(script),
str(root / 'scripts/Initialize-SecurityEnv.ps1'), str(root / 'scripts/Initialize-ApplicationVersions.ps1'), str(path)]
plans = []
for command in (bash, ps):
result = subprocess.run(command, env=env, capture_output=True, text=True, errors='replace', timeout=30)
assert (result.returncode == 0) == succeeds, (name, result.stdout, result.stderr)
assert 'private-fixture-must-not-be-printed' not in result.stdout + result.stderr
if succeeds:
plan = json.loads(result.stdout)
plan = plan if isinstance(plan, list) else [plan]
plans.append({entry['Key']: entry['Version'] for entry in plan})
assert path.read_bytes() == before, 'planning must not mutate private settings'
if succeeds:
assert plans[0] == plans[1], (name, plans)
if name in ('new install', 'legacy latest', 'legacy pinned', 'recorded product'):
assert plans[0]['WS_GATEWAY_VERSION'].startswith('3.25.0.20261009@sha256:')
assert plans[0]['MODEL_CONVERSION_WORKER_VERSION'].startswith('3.25.0.20261009.2@sha256:')
assert plans[0]['UPDATER_VERSION'] == 'latest', 'keep the existing updater maintenance channel'
if name == 'selected server':
assert set(plans[0]) == {'SERVER_VERSION', 'SERVER_STABLE_DIGEST'}
if name.startswith('watchtower'):
assert plans[0]['SERVER_VERSION'] == plans[0]['WS_GATEWAY_VERSION'] == 'latest'
assert plans[0]['SERVER_STABLE_DIGEST'].startswith('sha256:')
assert plans[0]['WEB_VERSION'] == ('latest-no-ssr' if name.endswith('variant') else 'latest')
if name == 'web variant':
assert '-no-ssr@sha256:' in plans[0]['WEB_VERSION']
print(name + ': passed in Bash planner and PowerShell')