64 lines
3.6 KiB
Python
64 lines
3.6 KiB
Python
#!/usr/bin/env python3
|
|
"""Prepare a fresh immutable candidate bundle. This command never launches the experiment."""
|
|
import argparse
|
|
import hashlib
|
|
import json
|
|
from pathlib import Path
|
|
import shutil
|
|
import subprocess
|
|
from build_saturation_observer import build
|
|
|
|
|
|
def sha(path):
|
|
return hashlib.sha256(path.read_bytes()).hexdigest()
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument("--output", type=Path, required=True)
|
|
parser.add_argument("--libraries", type=Path, required=True)
|
|
parser.add_argument("--image", required=True)
|
|
options = parser.parse_args()
|
|
source = Path(__file__).resolve().parent
|
|
repo = source.parents[2]
|
|
revision = subprocess.check_output(["git", "rev-parse", "HEAD"], cwd=repo, text=True).strip()
|
|
if subprocess.check_output(["git", "status", "--porcelain"], cwd=repo, text=True).strip():
|
|
raise RuntimeError("Commit and review the exact source before preparing immutable artifacts")
|
|
if not options.image.startswith("sha256:"):
|
|
raise ValueError("Use an immutable Linux .NET SDK image digest")
|
|
root = options.output.resolve()
|
|
root.mkdir(parents=True, exist_ok=False)
|
|
project = repo / "tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests.csproj"
|
|
command = ["dotnet", "publish", str(project), "-c", "Release", "-r", "linux-arm64", "--self-contained", "true",
|
|
"-p:RuntimeFrameworkVersion=10.0.14", "-p:PublishSingleFile=false", "-p:PublishTrimmed=false", "-p:UseAppHost=true",
|
|
"--artifacts-path", str(root / "build"), "-o", str(root / "app"), "-m:2", "--nologo"]
|
|
with (root / "publish.log").open("w") as log:
|
|
subprocess.run(command, cwd=repo, stdout=log, stderr=subprocess.STDOUT, check=True)
|
|
observer = build(root / "observer-build", options.libraries, True)
|
|
shutil.copytree(observer, root / "observer")
|
|
tools = root / "tools"
|
|
tools.mkdir()
|
|
for name in ["launch_saturation.py", "container_saturation.sh", "SATURATION.md"]:
|
|
shutil.copy2(source / name, tools / name)
|
|
manifest = {str(path.relative_to(root)): sha(path) for directory in ["app", "observer", "tools"]
|
|
for path in sorted((root / directory).rglob("*")) if path.is_file()}
|
|
runtime = json.loads((root / "app/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests.runtimeconfig.json").read_text())
|
|
included = runtime["runtimeOptions"]["includedFrameworks"]
|
|
if not included or any(value["version"] != "10.0.14" for value in included):
|
|
raise RuntimeError("Published app is not the prospectively fixed self-contained runtime")
|
|
receipt = {"protocol": "sdk2-saturation-v1", "sourceRevision": revision, "image": options.image,
|
|
"rid": "linux-arm64", "runtimeVersion": "10.0.14", "selfContained": True,
|
|
"canonicalCycles": 384, "completedRestarts": 96, "settlingCycles": 1, "maximumPhaseSeconds": 1800,
|
|
"windows": [[321, 352], [353, 384]], "observerBufferMiB": 16, "runtimeKeywords": "0x18", "rundown": False,
|
|
"acceptance": False, "publishCommand": command,
|
|
"testSourceSha256": sha(project.parent / "Sdk2LifecycleSoakTests.cs"),
|
|
"observerSourceSha256": sha(source / "SaturationObserver.cs"), "files": manifest}
|
|
receipt_path = root / "receipt.json"
|
|
receipt_path.write_text(json.dumps(receipt, indent=2) + "\n")
|
|
print(json.dumps({"bundle": str(root), "receiptSha256": sha(receipt_path), "sourceRevision": revision,
|
|
"launched": False}, indent=2))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|