diff options
| author | _ov4 <ov4@ov4.org> | 2026-10-21 11:22:38 +0000 |
|---|---|---|
| committer | _ov4 <ov4@ov4.org> | 2026-10-21 11:22:38 +0000 |
| commit | fcb9e2ef516cff0b6d5168bc6465e4615d2aa96e (patch) | |
| tree | ea490c33061dc0bdc56488f99a355c7626aca348 /bundle/scripts/smoke-package.py | |
| parent | 7b94b9003daa1126ce78df37481fc52774c2f0b4 (diff) | |
ci(bundle): publish portable Windows and macOS desktop packages
Build and check Bundle alongside each native compiler. Publish a single
Windows exe with an embedded compiler extracted into the startup directory,
and a macOS tar.xz containing the app and compiler. Check Linux without
publishing a desktop package and require all six nightly attachments.
Include licenses in embedded assets and app resources. Verify local builds,
package smoke checks and release replacement with a simulated GitHub API.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'bundle/scripts/smoke-package.py')
| -rw-r--r-- | bundle/scripts/smoke-package.py | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/bundle/scripts/smoke-package.py b/bundle/scripts/smoke-package.py new file mode 100644 index 0000000..98ee52a --- /dev/null +++ b/bundle/scripts/smoke-package.py @@ -0,0 +1,45 @@ +"""Check a portable desktop package without relying on an installed toolchain.""" + +from pathlib import Path +import os +import subprocess +import sys +import tempfile +import time + +root = Path(sys.argv[1]).resolve() +environment = os.environ.copy() +environment["PATH"] = os.pathsep.join((os.path.join(environment["SystemRoot"], "System32"), environment["SystemRoot"])) if sys.platform == "win32" else "/nonexistent" +with tempfile.TemporaryDirectory(prefix="cpsc bundle smoke ") as directory: + work = Path(directory) + if sys.platform == "win32": + assert root.is_file() and root.suffix == ".exe", "Expected a single portable .exe" + # Extraction happens before WebView startup and publishes a complete file by rename. + desktop = subprocess.Popen([str(root)], cwd=work, env=environment) + compiler = work / "cpsc.exe" + try: + deadline = time.monotonic() + 30 + while not compiler.is_file(): + assert desktop.poll() is None, "Desktop exited before extracting its compiler" + assert time.monotonic() < deadline, "Compiler extraction timed out" + time.sleep(0.1) + finally: + if desktop.poll() is None: + desktop.terminate() + desktop.wait(timeout=10) + else: + compilers = list(root.rglob("cpsc")) + assert len(compilers) == 1, f"Expected one packaged compiler, found {compilers}" + compiler = compilers[0] + assert compiler.with_name("cpsc-bundle").is_file(), "Missing desktop executable" + resources = compiler.parent.parent / "Resources" if sys.platform == "darwin" else compiler.parent + for filename in ("LICENSE", "ThirdPartyNotices.md", "licenses/vscode.txt", "licenses/plugin.md"): + assert (resources / filename).is_file(), f"Missing {filename}" + (work / "data.txt").write_text("relative file\n", encoding="utf-8") + source = work / "source file.cps" + source.write_text('DECLARE N : INTEGER\nINPUT N\nOUTPUT N\nDECLARE S : STRING\nOPENFILE "data.txt" FOR READ\nREADFILE "data.txt", S\nCLOSEFILE "data.txt"\nOUTPUT S\n', encoding="utf-8") + result = subprocess.run([str(compiler), str(source), "-r"], input=b"17\n", capture_output=True, cwd=work, env=environment, timeout=30) + assert result.returncode == 0, result.stderr + assert result.stdout.replace(b"\r\n", b"\n") == b"17\nrelative file\n", result.stdout + assert result.stderr == b"", result.stderr +print("Desktop package smoke passed: portable application, compiler, stdin and relative files.") |
