import os
import subprocess
import sys
from contextlib import contextmanager
from pathlib import Path
from typing import Dict, List, Optional, Union
@contextmanager
def group(name: str):
print(f"::group::{name}")
try:
yield
finally:
print("::endgroup::")
def run(
cmd: List[str],
env: Optional[Dict[str, str]] = None,
cwd: Optional[Union[str, Path]] = None,
check: bool = True,
capture_output: bool = False,
) -> subprocess.CompletedProcess:
cmd_str = " ".join(str(c) for c in cmd)
should_group = not capture_output
if should_group:
print(f"::group::{cmd_str}")
try:
run_env = os.environ.copy()
if env:
run_env.update(env)
result = subprocess.run(
cmd,
env=run_env,
cwd=cwd,
check=check,
text=True,
capture_output=capture_output
)
return result
except subprocess.CalledProcessError as e:
if should_group:
print(f"Command failed with exit code {e.returncode}")
raise
finally:
if should_group:
print("::endgroup::")
def fail(msg: str) -> None:
sys.exit(f"Error: {msg}")