Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions .github/actions/setup-cmux-tui-rust/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: Set up cmux-tui Rust
description: Install the repository-pinned cmux-tui Rust toolchain.

runs:
using: composite
steps:
- name: Install pinned Rust toolchain
shell: bash
env:
TOOLCHAIN_FILE: ${{ github.action_path }}/../../../cmux-tui/rust-toolchain.toml
run: |
if command -v python3 >/dev/null 2>&1; then
python_cmd=python3
elif command -v python >/dev/null 2>&1; then
python_cmd=python
else
echo "::error::Python is required to read the pinned Rust toolchain" >&2
exit 1
fi
"$python_cmd" <<'PY'
import os
import pathlib
import re
import subprocess

contents = pathlib.Path(os.environ["TOOLCHAIN_FILE"]).read_text(encoding="utf-8")

def value(name):
match = re.search(rf'^\s*{name}\s*=\s*"([^"]+)"', contents, re.MULTILINE)
if match is None:
raise SystemExit(f"missing {name} in cmux-tui/rust-toolchain.toml")
return match.group(1)

channel = value("channel")
profile = value("profile")
components_match = re.search(r"^\s*components\s*=\s*\[([^]]*)\]", contents, re.MULTILINE)
if components_match is None:
raise SystemExit("missing components in cmux-tui/rust-toolchain.toml")
components = re.findall(r'"([^"]+)"', components_match.group(1))

command = ["rustup", "toolchain", "install", channel, "--profile", profile]
for component in components:
command.extend(["--component", component])
subprocess.run(command, check=True)
subprocess.run(["rustup", "default", channel], check=True)

cargo = subprocess.run(
["rustup", "which", "cargo"],
check=True,
capture_output=True,
text=True,
).stdout.strip()
with open(os.environ["GITHUB_PATH"], "a", encoding="utf-8") as path_file:
print(pathlib.Path(cargo).parent, file=path_file)
PY
cargo --version
rustc --version
103 changes: 103 additions & 0 deletions .github/scripts/run-cmux-tui-core-tests-isolated.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#!/usr/bin/env python3
"""Run each cmux-tui-core Rust test in a fresh process."""

from __future__ import annotations

import argparse
import json
from pathlib import Path
import subprocess
import sys


def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser()
parser.add_argument("cargo_messages", type=Path)
parser.add_argument("core_root", type=Path)
return parser.parse_args()


def is_below(path: Path, root: Path) -> bool:
try:
path.relative_to(root)
except ValueError:
return False
return True


def test_binaries(cargo_messages: Path, core_root: Path) -> list[Path]:
binaries: dict[Path, set[str]] = {}
with cargo_messages.open(encoding="utf-8") as messages:
for line in messages:
try:
message = json.loads(line)
except json.JSONDecodeError:
continue
if message.get("reason") != "compiler-artifact":
continue
if not message.get("profile", {}).get("test"):
continue

target = message.get("target", {})
kinds = set(target.get("kind", []))
if not kinds.intersection({"lib", "test"}):
continue
source = target.get("src_path")
executable = message.get("executable")
if not source or not executable:
continue
if not is_below(Path(source).resolve(), core_root):
continue
binaries.setdefault(Path(executable).resolve(), set()).update(kinds)

library_binaries = [path for path, kinds in binaries.items() if "lib" in kinds]
if len(library_binaries) != 1:
raise SystemExit(
"expected one cmux-tui-core library test binary, "
f"found {len(library_binaries)}"
)
if not binaries:
raise SystemExit("cargo did not report any cmux-tui-core test binaries")
return sorted(binaries)


def tests_in(binary: Path) -> list[str]:
result = subprocess.run(
[str(binary), "--list"],
check=True,
stdout=subprocess.PIPE,
text=True,
)
tests = []
for line in result.stdout.splitlines():
name, separator, kind = line.rpartition(": ")
if separator and kind == "test":
tests.append(name)
if not tests:
raise SystemExit(f"{binary.name} did not list any tests")
if len(tests) != len(set(tests)):
raise SystemExit(f"{binary.name} listed duplicate test names")
return tests


def main() -> int:
args = parse_args()
core_root = args.core_root.resolve()
binaries = test_binaries(args.cargo_messages, core_root)
total = 0
for binary in binaries:
tests = tests_in(binary)
print(f"Running {len(tests)} tests from {binary.name} in fresh processes")
for index, test_name in enumerate(tests, start=1):
print(f"[{index}/{len(tests)}] {test_name}", flush=True)
subprocess.run(
[str(binary), test_name, "--exact", "--test-threads=1"],
check=True,
)
total += 1
print(f"Passed {total} isolated cmux-tui-core tests")
return 0


if __name__ == "__main__":
sys.exit(main())
Loading
Loading