Skip to content

Instantly share code, notes, and snippets.

@gotmax23
Created November 20, 2023 21:58
Show Gist options
  • Save gotmax23/390411232b95218f4935f1001e2b7be4 to your computer and use it in GitHub Desktop.
Save gotmax23/390411232b95218f4935f1001e2b7be4 to your computer and use it in GitHub Desktop.
# Copyright (C) 2023 Maxwell G <maxwell@gtmx.me>
# SPDX-License-Identifier: GPL-3.0-or-later
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or
# https://www.gnu.org/licenses/gpl-3.0.txt)
import datetime
import json
import logging
from functools import partial
from pathlib import Path
import shutil
from typing import Any, List
import typer
from antsibull_core.subprocess_util import log_run as _log_run
from antsibull_core.yaml import load_yaml_file, store_yaml_file
logging.basicConfig(level=logging.WARNING)
logger = logging.getLogger(__name__)
log_run = partial(_log_run, logger=logger)
def is_git_repo(base_directory: Path, directory: Path) -> bool:
repo = log_run(["git", "rev-parse", "--git-dir"], check=False, cwd=directory)
if repo.returncode == 128:
return False
git_directory = Path(repo.stdout.strip())
if not git_directory.is_absolute():
git_directory = directory.resolve() / git_directory
# If the collection base directory is a subdirectory of the git repository,
# we need to create an empty one for the collection.
return not base_directory.is_relative_to(git_directory.parent)
def create_stub_git_repo(directory: Path) -> None:
git_run = partial(log_run, cwd=directory)
git_run(["git", "init", "."])
git_run(["git", "add", "."])
git_run(["git", "commit", "--no-gpg-sign", "-m", "init"])
def remove_test_output_files(directory: Path):
if (output := directory / "tests" / "output").exists():
shutil.rmtree(output)
def get_errors(directory: Path) -> dict[str, Any]:
files = directory.glob("tests/output/bot/ansible-test-sanity-*.json")
data: dict[str, Any] = {}
for file in files:
with file.open() as fp:
data[file.name] = json.load(fp)
return data
def main(
collections: List[Path],
errors_path: Path = Path("error.yaml"),
tests: List[str] = typer.Option(
["ansible-doc", "compile", "validate-modules", "yamllint"],
"-t",
"--test",
),
collections_path: Path = typer.Option(Path(), "-C", "--path"),
clean: bool = typer.Option(True, help="Whether to clean the test output directory"),
):
errors = {"collections": {}}
for collection in collections:
directory = collections_path / collection
if not is_git_repo(directory.parent.resolve(), directory):
create_stub_git_repo(directory)
galaxy = load_yaml_file(directory / "galaxy.yml")
namespace_name = galaxy["namespace"] + "." + galaxy["name"]
if clean:
remove_test_output_files(directory)
test_args = [f"--test={test}" for test in tests]
args = ["ansible-test", "sanity", *test_args, "--docker", "--lint"]
typer.secho(f"* Running: {args} for {collection}", fg="blue")
now = datetime.datetime.now()
cmd = log_run(
args,
stdout_loglevel="error",
stderr_loglevel="error",
cwd=directory,
check=False,
)
after = datetime.datetime.now()
total = after - now
runtime = f"{total.seconds/60:.2f}"
typer.secho(
f"* Finished in {runtime} minutes",
fg="green" if not cmd.returncode else "red",
)
cerrors = errors["collections"][namespace_name] = {}
cerrors["cmd"] = args
cerrors["returncode"] = cmd.returncode
cerrors["stdout"] = cmd.stdout
cerrors["stderr"] = cmd.stderr
cerrors["runtime"] = total.seconds / 60
cerrors["test_json"] = get_errors()
store_yaml_file(errors_path, errors)
errors["total_runtime"] = sum(
cerrors["runtime"] for cerrors in errors["collections"].values()
)
store_yaml_file(errors_path, errors)
if __name__ == "__main__":
typer.run(main)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment