feat(update): add verifiable release manifest
This commit is contained in:
@@ -1,6 +1,11 @@
|
||||
import hashlib
|
||||
import json
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
from _helpers import REPO_ROOT
|
||||
from app import release_manifest
|
||||
from app import version
|
||||
|
||||
|
||||
@@ -88,6 +93,59 @@ class PackagingTests(unittest.TestCase):
|
||||
self.assertIn('Compress-ArchiveWithRetry', script)
|
||||
self.assertIn('Start-Sleep -Seconds $DelaySeconds', script)
|
||||
self.assertIn('Assert-NoExcludedData -Root $releaseDir', script)
|
||||
self.assertIn('-m app.release_manifest manifest', script)
|
||||
self.assertIn('-m app.release_manifest metadata', script)
|
||||
self.assertIn('release-metadata.json', script)
|
||||
|
||||
def make_release_dir(self, root, app_version="1.2.3"):
|
||||
release_dir = Path(root) / "release"
|
||||
(release_dir / "_internal").mkdir(parents=True)
|
||||
(release_dir / "cmshopee.exe").write_bytes(b"exe")
|
||||
(release_dir / "_internal" / "runtime.dll").write_bytes(b"runtime")
|
||||
(release_dir / "version.txt").write_text(app_version, encoding="ascii")
|
||||
(release_dir / "README.txt").write_text("说明", encoding="utf-8")
|
||||
return release_dir
|
||||
|
||||
def test_release_manifest_covers_program_files_with_hashes(self):
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
release_dir = self.make_release_dir(temp_dir)
|
||||
output = release_manifest.write_package_manifest(release_dir, "1.2.3")
|
||||
manifest = json.loads(output.read_text(encoding="utf-8"))
|
||||
|
||||
self.assertEqual("cmshopee-portable-v1", manifest["package_format"])
|
||||
self.assertEqual("1.2.3", manifest["app_version"])
|
||||
self.assertEqual("cmshopee.exe", manifest["entry_point"])
|
||||
paths = [item["path"] for item in manifest["files"]]
|
||||
self.assertEqual(len(paths), len(set(path.casefold() for path in paths)))
|
||||
self.assertNotIn("package-manifest.json", paths)
|
||||
self.assertIn("_internal/runtime.dll", paths)
|
||||
exe = next(item for item in manifest["files"] if item["path"] == "cmshopee.exe")
|
||||
self.assertEqual(3, exe["size_bytes"])
|
||||
self.assertEqual(hashlib.sha256(b"exe").hexdigest(), exe["sha256"])
|
||||
|
||||
def test_release_manifest_rejects_user_data_and_version_mismatch(self):
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
release_dir = self.make_release_dir(temp_dir)
|
||||
(release_dir / "data").mkdir()
|
||||
with self.assertRaises(release_manifest.ReleaseManifestError):
|
||||
release_manifest.build_package_manifest(release_dir, "1.2.3")
|
||||
|
||||
(release_dir / "data").rmdir()
|
||||
with self.assertRaises(release_manifest.ReleaseManifestError):
|
||||
release_manifest.build_package_manifest(release_dir, "9.9.9")
|
||||
|
||||
def test_release_metadata_matches_zip_size_and_hash(self):
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
zip_path = Path(temp_dir) / "蝦皮圈優化助手1.2.3.zip"
|
||||
zip_path.write_bytes(b"portable-zip")
|
||||
metadata = release_manifest.build_release_metadata(zip_path, "1.2.3")
|
||||
release = metadata["release"]
|
||||
|
||||
self.assertEqual(zip_path.stat().st_size, release["size_bytes"])
|
||||
self.assertEqual(
|
||||
hashlib.sha256(b"portable-zip").hexdigest(), release["sha256"]
|
||||
)
|
||||
self.assertEqual("cmshopee-portable-v1", release["package_format"])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user