2ba027098f
新增 APK/IPA 轨道和 copy_artifact.sh(本地目录或 container:/dir)。 push 必须委托该脚本,禁止在 makefile 里内联 docker cp。
120 lines
4.2 KiB
Python
120 lines
4.2 KiB
Python
from __future__ import annotations
|
|
|
|
import os
|
|
import subprocess
|
|
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
REPO_ROOT = Path(__file__).resolve().parents[1]
|
|
SCRIPT = REPO_ROOT / "skills" / "builder" / "scripts" / "copy_artifact.sh"
|
|
|
|
|
|
def git(cwd: Path, *args: str) -> None:
|
|
result = subprocess.run(
|
|
["git", *args],
|
|
cwd=cwd,
|
|
text=True,
|
|
capture_output=True,
|
|
check=False,
|
|
env={
|
|
**os.environ,
|
|
"GIT_AUTHOR_NAME": "Test",
|
|
"GIT_AUTHOR_EMAIL": "test@example.com",
|
|
"GIT_COMMITTER_NAME": "Test",
|
|
"GIT_COMMITTER_EMAIL": "test@example.com",
|
|
},
|
|
)
|
|
if result.returncode != 0:
|
|
raise AssertionError(f"git {args} failed: {result.stderr}")
|
|
|
|
|
|
class CopyArtifactTests(unittest.TestCase):
|
|
def test_local_copy_and_alias(self) -> None:
|
|
with tempfile.TemporaryDirectory() as temp:
|
|
root = Path(temp)
|
|
git(root, "init", "-b", "main")
|
|
git(root, "config", "user.email", "test@example.com")
|
|
git(root, "config", "user.name", "Test")
|
|
src = root / "app.apk"
|
|
src.write_bytes(b"apk")
|
|
git(root, "add", "app.apk")
|
|
git(root, "commit", "-m", "apk")
|
|
dest = root / "out"
|
|
result = subprocess.run(
|
|
[str(SCRIPT), "-d", str(dest), "-a", "latest.apk", str(src)],
|
|
cwd=root,
|
|
capture_output=True,
|
|
text=True,
|
|
check=False,
|
|
)
|
|
self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
|
|
self.assertTrue((dest / "app.apk").is_file())
|
|
self.assertTrue((dest / "latest.apk").is_file())
|
|
self.assertEqual((dest / "latest.apk").read_bytes(), b"apk")
|
|
self.assertIn("copy_artifact: 1 file(s)", result.stdout)
|
|
|
|
def test_dirty_tree_requires_allow(self) -> None:
|
|
with tempfile.TemporaryDirectory() as temp:
|
|
root = Path(temp)
|
|
git(root, "init", "-b", "main")
|
|
git(root, "config", "user.email", "test@example.com")
|
|
git(root, "config", "user.name", "Test")
|
|
src = root / "app.apk"
|
|
src.write_bytes(b"apk")
|
|
git(root, "add", "app.apk")
|
|
git(root, "commit", "-m", "apk")
|
|
src.write_bytes(b"changed")
|
|
dest = root / "out"
|
|
blocked = subprocess.run(
|
|
[str(SCRIPT), "-d", str(dest), str(src)],
|
|
cwd=root,
|
|
capture_output=True,
|
|
text=True,
|
|
check=False,
|
|
)
|
|
self.assertEqual(blocked.returncode, 3, blocked.stderr)
|
|
allowed = subprocess.run(
|
|
[str(SCRIPT), "-d", str(dest), str(src)],
|
|
cwd=root,
|
|
capture_output=True,
|
|
text=True,
|
|
check=False,
|
|
env={**os.environ, "ALLOW_UNCOMMITTED": "1"},
|
|
)
|
|
self.assertEqual(allowed.returncode, 0, allowed.stdout + allowed.stderr)
|
|
|
|
def test_dry_run_docker_dest_prints_docker_cp(self) -> None:
|
|
with tempfile.TemporaryDirectory() as temp:
|
|
root = Path(temp)
|
|
git(root, "init", "-b", "main")
|
|
git(root, "config", "user.email", "test@example.com")
|
|
git(root, "config", "user.name", "Test")
|
|
src = root / "app.apk"
|
|
src.write_bytes(b"apk")
|
|
git(root, "add", "app.apk")
|
|
git(root, "commit", "-m", "apk")
|
|
result = subprocess.run(
|
|
[
|
|
str(SCRIPT),
|
|
"--dry-run",
|
|
"-d",
|
|
"file-server:/srv",
|
|
"-a",
|
|
"latest.apk",
|
|
str(src),
|
|
],
|
|
cwd=root,
|
|
capture_output=True,
|
|
text=True,
|
|
check=False,
|
|
)
|
|
self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
|
|
self.assertIn("docker cp", result.stdout)
|
|
self.assertIn("file-server:/srv/app.apk", result.stdout)
|
|
self.assertIn("file-server:/srv/latest.apk", result.stdout)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|