Prepare 0.2.0 usability release and refresh desktop demo
This commit is contained in:
1 parent
a094fa46b5
commit
ab05b24dee
54 files changed
+4888
-234
No files matched your search
@@ -10,7 +10,7 @@ fi
|
||||
# /releases/latest excludes prereleases. Include every published release instead,
|
||||
# including nightlies, and sort by publication time across all API pages.
|
||||
latest_tag="$(gh api --paginate --slurp "repos/$GITHUB_REPOSITORY/releases?per_page=100" \
|
||||
--jq '[.[][] | select(.draft == false and .published_at != null)] | sort_by(.published_at) | last | .tag_name // empty')"
|
||||
| jq -r '[.[][] | select(.draft == false and .published_at != null)] | sort_by(.published_at) | last | .tag_name // empty')"
|
||||
if [ -n "$latest_tag" ]; then
|
||||
# Resolve the tag itself, not target_commitish (which can be a moving branch).
|
||||
released_sha="$(git rev-parse --verify "refs/tags/$latest_tag^{commit}")"
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
"""Exercise the real nightly decision script without GitHub or repository mutations."""
|
||||
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
|
||||
SCRIPT = Path(__file__).resolve().parents[1] / "nightly.sh"
|
||||
|
||||
|
||||
def release(tag, published, *, draft=False, prerelease=False):
|
||||
return {"tag_name": tag, "published_at": published, "draft": draft,
|
||||
"prerelease": prerelease, "target_commitish": "main"}
|
||||
|
||||
|
||||
class NightlyDecision(unittest.TestCase):
|
||||
def run_decision(self, pages, refs=None, *, event="schedule", sha="current", api_fail=False):
|
||||
self.assertIsNotNone(shutil.which("jq"), "install jq to run packaging checks")
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
root = Path(directory)
|
||||
output = root / "output"
|
||||
summary = root / "summary"
|
||||
calls = root / "calls"
|
||||
output.touch()
|
||||
summary.touch()
|
||||
for command, body in {
|
||||
"gh": '''import json, os, sys
|
||||
args = sys.argv[1:]
|
||||
with open(os.environ["CALLS"], "a") as log: log.write(json.dumps(args) + "\\n")
|
||||
if args != ["api", "--paginate", "--slurp", "repos/test/project/releases?per_page=100"]:
|
||||
sys.exit("unexpected gh invocation (slurp and jq must not be combined)")
|
||||
if os.environ["API_FAIL"] == "1": sys.exit("mock API failure")
|
||||
print(os.environ["PAGES"])
|
||||
''',
|
||||
"git": '''import json, os, sys
|
||||
args = sys.argv[1:]
|
||||
with open(os.environ["CALLS"], "a") as log: log.write(json.dumps(args) + "\\n")
|
||||
refs = json.loads(os.environ["REFS"])
|
||||
if len(args) != 3 or args[:2] != ["rev-parse", "--verify"] or args[2] not in refs:
|
||||
sys.exit("missing tag")
|
||||
print(refs[args[2]])
|
||||
''',
|
||||
}.items():
|
||||
path = root / command
|
||||
path.write_text("#!/usr/bin/env python3\n" + body, encoding="utf-8")
|
||||
path.chmod(0o755)
|
||||
env = {"PATH": str(root) + os.pathsep + os.environ["PATH"],
|
||||
"GITHUB_EVENT_NAME": event, "GITHUB_REPOSITORY": "test/project",
|
||||
"GITHUB_SHA": sha, "GITHUB_OUTPUT": str(output),
|
||||
"GITHUB_STEP_SUMMARY": str(summary), "CALLS": str(calls),
|
||||
"PAGES": json.dumps(pages), "REFS": json.dumps(refs or {}),
|
||||
"API_FAIL": "1" if api_fail else "0"}
|
||||
result = subprocess.run(["bash", str(SCRIPT)], env=env, capture_output=True, text=True, check=False)
|
||||
return result, output.read_text(), summary.read_text(), calls.read_text() if calls.exists() else ""
|
||||
|
||||
def test_newest_published_prerelease_across_pages_skips_exact_tag_commit(self):
|
||||
pages = [[release("v1", "2026-01-01T00:00:00Z")],
|
||||
[release("v2-nightly", "2026-01-03T00:00:00Z", prerelease=True),
|
||||
release("v3-draft", "2026-01-04T00:00:00Z", draft=True)]]
|
||||
result, output, summary, calls = self.run_decision(pages, {"refs/tags/v2-nightly^{commit}": "current"})
|
||||
self.assertEqual(result.returncode, 0, result.stderr)
|
||||
self.assertEqual(output, "build=false\n")
|
||||
self.assertIn("v2-nightly", summary)
|
||||
self.assertIn("refs/tags/v2-nightly^{commit}", calls)
|
||||
self.assertNotIn("v3-draft^{commit}", calls)
|
||||
|
||||
def test_changed_commit_builds(self):
|
||||
result, output, _, _ = self.run_decision([[release("v1", "2026-01-01T00:00:00Z")]],
|
||||
{"refs/tags/v1^{commit}": "previous"})
|
||||
self.assertEqual(result.returncode, 0, result.stderr)
|
||||
self.assertEqual(output, "build=true\n")
|
||||
|
||||
def test_no_published_release_builds(self):
|
||||
for pages in [[], [[]], [[release("draft", None, draft=True)]]]:
|
||||
with self.subTest(pages=pages):
|
||||
result, output, _, calls = self.run_decision(pages)
|
||||
self.assertEqual(result.returncode, 0, result.stderr)
|
||||
self.assertEqual(output, "build=true\n")
|
||||
self.assertNotIn("rev-parse", calls)
|
||||
|
||||
def test_non_schedule_does_not_query_github(self):
|
||||
for event in ["push", "workflow_dispatch"]:
|
||||
with self.subTest(event=event):
|
||||
result, output, _, calls = self.run_decision([], event=event, api_fail=True)
|
||||
self.assertEqual(result.returncode, 0, result.stderr)
|
||||
self.assertEqual(output, "build=true\n")
|
||||
self.assertEqual(calls, "")
|
||||
|
||||
def test_api_failure_does_not_report_build_or_skip(self):
|
||||
result, output, _, _ = self.run_decision([], api_fail=True)
|
||||
self.assertNotEqual(result.returncode, 0)
|
||||
self.assertEqual(output, "")
|
||||
|
||||
def test_missing_tag_fails_instead_of_using_moving_target_commitish(self):
|
||||
result, output, _, _ = self.run_decision([[release("missing", "2026-01-01T00:00:00Z")]])
|
||||
self.assertNotEqual(result.returncode, 0)
|
||||
self.assertEqual(output, "")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in new issue
Block a user