155 lines
6.2 KiB
Python
155 lines
6.2 KiB
Python
import importlib.util
|
|
import json
|
|
import tempfile
|
|
import unittest
|
|
import sys
|
|
from pathlib import Path
|
|
from unittest import mock
|
|
|
|
|
|
MODULE_PATH = Path(__file__).resolve().parents[1] / "release_mac_alpha.py"
|
|
sys.path.insert(0, str(MODULE_PATH.parent))
|
|
SPEC = importlib.util.spec_from_file_location("release_mac_alpha", MODULE_PATH)
|
|
release = importlib.util.module_from_spec(SPEC)
|
|
SPEC.loader.exec_module(release)
|
|
|
|
|
|
class ReleaseHarnessTests(unittest.TestCase):
|
|
def test_parse_revision_accepts_current_alpha_contract(self):
|
|
self.assertEqual(release.parse_revision_from_version("0.1.0-alpha.12"), 12)
|
|
with self.assertRaises(release.ReleaseError):
|
|
release.parse_revision_from_version("0.1.0")
|
|
|
|
def test_replace_exact_regex_fails_closed_on_ambiguous_input(self):
|
|
self.assertEqual(
|
|
release.replace_exact_regex(
|
|
"revision=2",
|
|
r"revision=\d+",
|
|
"revision=3",
|
|
label="revision",
|
|
),
|
|
"revision=3",
|
|
)
|
|
with self.assertRaises(release.ReleaseError):
|
|
release.replace_exact_regex(
|
|
"revision=2\nrevision=2",
|
|
r"revision=\d+",
|
|
"revision=3",
|
|
label="revision",
|
|
)
|
|
|
|
def test_set_release_version_updates_source_and_independent_contract_test(self):
|
|
with tempfile.TemporaryDirectory() as temporary:
|
|
root = Path(temporary)
|
|
source = root / "ProjectQuintReleaseVersion.cs"
|
|
tests = root / "ProjectQuintReleaseVersionTests.cs"
|
|
source.write_text(
|
|
"public const int ChannelRevision = 2;\n"
|
|
"public const int BuildNumber = 2;\n",
|
|
encoding="utf-8",
|
|
)
|
|
tests.write_text(
|
|
"Assert.That(ProjectQuintReleaseVersion.ChannelRevision, Is.EqualTo(2));\n"
|
|
"Assert.That(ProjectQuintReleaseVersion.BuildNumber, Is.EqualTo(2));\n"
|
|
'Assert.That(ProjectQuintReleaseVersion.DisplayVersion, Is.EqualTo("0.1.0-alpha.2"));\n'
|
|
'Is.EqualTo("0.1.0-alpha.2 (build 2)"));\n',
|
|
encoding="utf-8",
|
|
)
|
|
with mock.patch.object(release, "VERSION_SOURCE", source), mock.patch.object(
|
|
release, "VERSION_TEST", tests
|
|
):
|
|
release.set_release_version(3)
|
|
|
|
self.assertIn("ChannelRevision = 3", source.read_text())
|
|
self.assertIn("BuildNumber = 3", source.read_text())
|
|
self.assertIn("0.1.0-alpha.3", tests.read_text())
|
|
self.assertIn("build 3", tests.read_text())
|
|
|
|
def test_update_site_writes_download_manifest_and_one_changelog_entry(self):
|
|
with tempfile.TemporaryDirectory() as temporary:
|
|
root = Path(temporary)
|
|
download = root / "download.astro"
|
|
changelog = root / "changelog.astro"
|
|
manifest = root / "latest.json"
|
|
appcast = root / "appcast.xml"
|
|
readme = root / "README.md"
|
|
download.write_text(
|
|
'href="/downloads/0.1.0-alpha.2/ProjectQuint-0.1.0-alpha.2-macOS-universal.dmg"\n'
|
|
"<strong>0.1.0 ALPHA 2</strong>\n"
|
|
"<div><dt>VERSION</dt><dd>0.1.0-alpha.2</dd></div>\n"
|
|
"<div><dt>SIZE</dt><dd>77.7 MB</dd></div>\n"
|
|
f"<code>{'a' * 64}</code>\n",
|
|
encoding="utf-8",
|
|
)
|
|
changelog.write_text(' <section class="timeline">\n', encoding="utf-8")
|
|
manifest.write_text("{}\n", encoding="utf-8")
|
|
appcast.write_text("", encoding="utf-8")
|
|
readme.write_text("# Site\n", encoding="utf-8")
|
|
digest = "b" * 64
|
|
signature = "A" * 86 + "=="
|
|
|
|
patches = [
|
|
mock.patch.object(release, "DOWNLOAD_PAGE", download),
|
|
mock.patch.object(release, "CHANGELOG_PAGE", changelog),
|
|
mock.patch.object(release, "UPDATE_MANIFEST", manifest),
|
|
mock.patch.object(release, "SPARKLE_APPCAST", appcast),
|
|
mock.patch.object(release, "SITE_README", readme),
|
|
]
|
|
for patch in patches:
|
|
patch.start()
|
|
try:
|
|
release.update_site(
|
|
3,
|
|
digest,
|
|
80_000_000,
|
|
signature,
|
|
"Release title",
|
|
["Change one", "Change two"],
|
|
"2026-07-29T18:00:00+09:00",
|
|
)
|
|
release.update_site(
|
|
3,
|
|
digest,
|
|
80_000_000,
|
|
signature,
|
|
"Release title",
|
|
["Change one", "Change two"],
|
|
"2026-07-29T18:00:00+09:00",
|
|
)
|
|
finally:
|
|
for patch in reversed(patches):
|
|
patch.stop()
|
|
|
|
self.assertIn("0.1.0-alpha.3", download.read_text())
|
|
self.assertIn("80.0 MB", download.read_text())
|
|
self.assertEqual(changelog.read_text().count("0.1.0-ALPHA.3"), 1)
|
|
self.assertEqual(readme.read_text().count("## 0.1.0-alpha.3 release"), 1)
|
|
data = json.loads(manifest.read_text())
|
|
self.assertEqual(data["buildNumber"], 3)
|
|
self.assertEqual(data["sha256"], digest)
|
|
self.assertEqual(data["sizeBytes"], 80_000_000)
|
|
appcast_text = appcast.read_text()
|
|
self.assertIn("0.1.0-alpha.3", appcast_text)
|
|
self.assertIn('sparkle:version>3</sparkle:version', appcast_text)
|
|
self.assertIn('length="80000000"', appcast_text)
|
|
self.assertIn(signature, appcast_text)
|
|
|
|
def test_build_stable_does_not_block_for_a_running_existing_app(self):
|
|
with mock.patch.object(release, "run") as run:
|
|
app = release.build_stable()
|
|
|
|
self.assertEqual(app, release.STABLE_APP)
|
|
run.assert_called_once()
|
|
self.assertEqual(
|
|
run.call_args.args[0],
|
|
[release.ROOT / "Tools/build-mac-stable-release.sh"],
|
|
)
|
|
self.assertEqual(
|
|
run.call_args.kwargs["env"]["PROJECTQUINT_BUILD_PATH"],
|
|
str(release.STABLE_APP),
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|