bb15b750fb
复用现有 Docker 和 Nuitka 流程,隔离架构镜像并支持 aarch64 标签。已通过 47 项测试、代码及文档门禁,并完成 Python 3.10 ARM64 wheel 构建、隔离导入与内容审计。
122 lines
4.1 KiB
Python
122 lines
4.1 KiB
Python
"""Exercise the Windows launcher without downloading or compiling Docker images."""
|
|
|
|
import json
|
|
import shutil
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
POWERSHELL = shutil.which("powershell")
|
|
REPO_ROOT = Path(__file__).resolve().parents[1]
|
|
pytestmark = pytest.mark.skipif(not POWERSHELL, reason="Windows PowerShell is required")
|
|
|
|
|
|
def run_launcher(tmp_path, arguments, image_architecture):
|
|
docker_dir = tmp_path / "build" / "wheel" / "docker"
|
|
docker_dir.mkdir(parents=True)
|
|
shutil.copy2(REPO_ROOT / "build/wheel/docker/run.ps1", docker_dir)
|
|
(docker_dir / "entrypoint.sh").write_text("#!/bin/bash\n", encoding="utf-8")
|
|
parameters = {}
|
|
iterator = iter(arguments)
|
|
for argument in iterator:
|
|
parameters[argument.lstrip("-")] = (
|
|
True if argument == "-SkipImageBuild" else next(iterator)
|
|
)
|
|
(tmp_path / "arguments.json").write_text(json.dumps(parameters), encoding="utf-8")
|
|
harness = tmp_path / "harness.ps1"
|
|
harness.write_text(
|
|
"""
|
|
$ErrorActionPreference = 'Stop'
|
|
$global:Calls = [System.Collections.Generic.List[object]]::new()
|
|
function docker {
|
|
$global:Calls.Add(@($args))
|
|
$global:LASTEXITCODE = 0
|
|
if ($args[0] -eq 'version') { return 'linux' }
|
|
if ($args[0] -eq 'image') { return '__ARCH__' }
|
|
}
|
|
$decoded = Get-Content (Join-Path $PSScriptRoot 'arguments.json') -Raw | ConvertFrom-Json
|
|
$parameters = @{}
|
|
foreach ($property in $decoded.PSObject.Properties) { $parameters[$property.Name] = $property.Value }
|
|
try {
|
|
& (Join-Path $PSScriptRoot 'build/wheel/docker/run.ps1') @parameters
|
|
} finally {
|
|
ConvertTo-Json -InputObject @($global:Calls.ToArray()) -Depth 5 |
|
|
Set-Content (Join-Path $PSScriptRoot 'calls.json') -Encoding UTF8
|
|
}
|
|
""".replace("__ARCH__", image_architecture),
|
|
encoding="utf-8",
|
|
)
|
|
result = subprocess.run(
|
|
[POWERSHELL, "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", str(harness)],
|
|
capture_output=True,
|
|
text=True,
|
|
check=False,
|
|
)
|
|
calls = json.loads((tmp_path / "calls.json").read_text(encoding="utf-8-sig"))
|
|
return result, calls
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"arguments,image_architecture,platform,architecture,image_name",
|
|
[
|
|
([], "amd64", "linux/amd64", "x86_64", "orisys-manylinux"),
|
|
(
|
|
["-Architecture", "aarch64"],
|
|
"arm64",
|
|
"linux/arm64",
|
|
"aarch64",
|
|
"orisys-manylinux-aarch64",
|
|
),
|
|
(
|
|
["-Architecture", "AARCH64"],
|
|
"arm64",
|
|
"linux/arm64",
|
|
"aarch64",
|
|
"orisys-manylinux-aarch64",
|
|
),
|
|
],
|
|
)
|
|
def test_architecture_controls_build_and_run(
|
|
tmp_path, arguments, image_architecture, platform, architecture, image_name
|
|
):
|
|
result, calls = run_launcher(tmp_path, arguments, image_architecture)
|
|
assert result.returncode == 0, result.stderr
|
|
build = next(call for call in calls if call[0] == "build")
|
|
run = next(call for call in calls if call[0] == "run")
|
|
assert build[build.index("--platform") + 1] == platform
|
|
assert build[build.index("--build-arg") + 1] == f"MANYLINUX_ARCH={architecture}"
|
|
assert build[build.index("-t") + 1] == image_name
|
|
assert run[run.index("--platform") + 1] == platform
|
|
assert run[-1] == image_name
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"image_architecture,success", [("arm64", True), ("amd64", False)]
|
|
)
|
|
def test_reused_image_must_match_requested_architecture(
|
|
tmp_path, image_architecture, success
|
|
):
|
|
result, calls = run_launcher(
|
|
tmp_path,
|
|
[
|
|
"-Architecture",
|
|
"aarch64",
|
|
"-SkipImageBuild",
|
|
"-ImageName",
|
|
"custom-arm",
|
|
"-PythonVersions",
|
|
"3.10",
|
|
],
|
|
image_architecture,
|
|
)
|
|
assert not any(call[0] == "build" for call in calls)
|
|
assert (result.returncode == 0) == success
|
|
runs = [call for call in calls if call[0] == "run"]
|
|
if success:
|
|
assert runs[0][-1] == "custom-arm"
|
|
assert "ORISYS_PYTHON_TAGS=cp310-cp310" in runs[0]
|
|
else:
|
|
assert not runs
|
|
assert "architecture" in result.stderr.lower()
|