SHA256
Move workflows into Gitea's workflow directory and use the supplied ubuntu-latest and macos-arm64 labels. Provision the Android SDK, require KVM without changing host permissions, support SHA-256 checkout and Gitea artifact uploads, and isolate scratch output on persistent runners. Skip untrusted fork PRs and keep release builds unsigned because Gitea ignores GitHub environment approval gates. Local workflow lint, repository invariants, ten preflight regressions, eight evidence-verifier tests, inline shell checks, scratch cleanup and SHA-256 fetch checks pass; remote runner execution remains unverified.
68 lines
2.9 KiB
Python
68 lines
2.9 KiB
Python
#!/usr/bin/env python3
|
|
"""Test runner prerequisite decisions with fake tools, not actual Apple SDKs."""
|
|
import os
|
|
from pathlib import Path
|
|
import subprocess
|
|
import tempfile
|
|
import unittest
|
|
|
|
SCRIPT = Path(__file__).with_name("check-ci-runner.sh")
|
|
|
|
|
|
class RunnerPrerequisiteTests(unittest.TestCase):
|
|
def run_check(self, mode, system="Linux", architecture="x86_64", missing=None, broken_xcode=False):
|
|
with tempfile.TemporaryDirectory(prefix="yuvomi-runner-test-") as temporary:
|
|
directory = Path(temporary)
|
|
for name in ["git", "curl", "unzip", "python3", "xcodebuild", "xcrun"]:
|
|
if name == missing:
|
|
continue
|
|
path = directory / name
|
|
status = 1 if name == "xcodebuild" and broken_xcode else 0
|
|
path.write_text(f"#!/bin/sh\nexit {status}\n")
|
|
path.chmod(0o700)
|
|
uname = directory / "uname"
|
|
uname.write_text('#!/bin/sh\ncase "$1" in -s) echo "$TEST_SYSTEM";; -m) echo "$TEST_ARCH";; esac\n')
|
|
uname.chmod(0o700)
|
|
return subprocess.run(["/bin/bash", str(SCRIPT), mode], capture_output=True, text=True,
|
|
env={**os.environ, "PATH": temporary, "TEST_SYSTEM": system,
|
|
"TEST_ARCH": architecture})
|
|
|
|
def test_android_accepts_linux_x64(self):
|
|
self.assertEqual(self.run_check("android").returncode, 0)
|
|
|
|
def test_android_rejects_arm(self):
|
|
self.assertNotEqual(self.run_check("android", architecture="aarch64").returncode, 0)
|
|
|
|
def test_android_rejects_macos(self):
|
|
self.assertNotEqual(self.run_check("android", system="Darwin").returncode, 0)
|
|
|
|
def test_ios_accepts_native_arm_with_tools(self):
|
|
self.assertEqual(self.run_check("ios", system="Darwin", architecture="arm64").returncode, 0)
|
|
|
|
def test_ios_rejects_rosetta_or_intel(self):
|
|
self.assertNotEqual(self.run_check("ios", system="Darwin").returncode, 0)
|
|
|
|
def test_ios_rejects_linux(self):
|
|
self.assertNotEqual(self.run_check("ios", architecture="arm64").returncode, 0)
|
|
|
|
def test_missing_python_is_actionable(self):
|
|
result = self.run_check("android", missing="python3")
|
|
self.assertNotEqual(result.returncode, 0)
|
|
self.assertIn("install python3", result.stderr)
|
|
|
|
def test_missing_full_xcode_fails(self):
|
|
result = self.run_check("ios", system="Darwin", architecture="arm64", missing="xcodebuild")
|
|
self.assertNotEqual(result.returncode, 0)
|
|
self.assertIn("full Xcode", result.stderr)
|
|
|
|
def test_broken_xcode_fails(self):
|
|
self.assertNotEqual(self.run_check("ios", system="Darwin", architecture="arm64",
|
|
broken_xcode=True).returncode, 0)
|
|
|
|
def test_unknown_mode_fails(self):
|
|
self.assertNotEqual(self.run_check("other").returncode, 0)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|