generated from tophat/new-project-kit
-
Notifications
You must be signed in to change notification settings - Fork 37
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: drop python 3.6 support (#604)
* feat: drop python 3.6 support BREAKING CHANGE: Python 3.6 is end of life as of December 2021. You can continue to use Syrupy v2 for Python 3.6 compatibility. Security fixes and critical bug fixes may be backported to Syrupy v2 if requested in a GitHub issue (or private security disclosure).
- Loading branch information
Showing
9 changed files
with
605 additions
and
603 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
3.9.0 | ||
3.10.4 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,212 +0,0 @@ | ||
import os | ||
import subprocess | ||
from typing import ( | ||
TYPE_CHECKING, | ||
Any, | ||
Callable, | ||
Optional, | ||
Tuple, | ||
) | ||
|
||
from github import ( | ||
Github, | ||
GithubException, | ||
UnknownObjectException, | ||
) | ||
|
||
if TYPE_CHECKING: | ||
from subprocess import CompletedProcess | ||
|
||
from github.Commit import Commit | ||
|
||
BENCH_COMMAND = "pytest benchmarks/test.py -qq --snapshot-update" | ||
BENCH_PERF_FILE = "current.json" | ||
BENCH_REF_FILE = "master.json" | ||
GH_BENCH_FILE_PATH = "runs" | ||
GH_BENCH_BRANCH = "benchmarks" | ||
GH_BRANCH_REF = "master" | ||
GH_REPO = "tophat/syrupy" | ||
GH_STATUS_CONTEXT = "Syrupy CICD / Benchmark" | ||
GH_STATUS_DESC_DELIM = "\n" * 3 | ||
|
||
|
||
def get_req_env(var_name: str) -> str: | ||
""" | ||
Try to get environment variable and exits if not available | ||
""" | ||
try: | ||
return os.environ[var_name] | ||
except KeyError: | ||
print(f"Missing required environment variable '{var_name}'.") | ||
exit(1) | ||
|
||
|
||
def get_commit(github: "Github") -> "Commit": | ||
""" | ||
Get current commit the github ci run is for | ||
""" | ||
commit_sha = get_req_env("COMMIT_SHA") | ||
return github.get_repo(GH_REPO).get_commit(commit_sha) | ||
|
||
|
||
def get_branch() -> Optional[str]: | ||
""" | ||
Get current branch the github ci run is for | ||
""" | ||
github_ref = get_req_env("GITHUB_REF") | ||
return github_ref.replace("refs/heads/", "") if github_ref else None | ||
|
||
|
||
def get_target_url() -> str: | ||
""" | ||
Get url to benchmark result | ||
""" | ||
repo_url = f"https://github.com/{GH_REPO}" | ||
all_results_url = f"{repo_url}/tree/{GH_BENCH_BRANCH}/{GH_BENCH_FILE_PATH}" | ||
commit_sha = get_req_env("COMMIT_SHA") | ||
return all_results_url + (f"/{commit_sha}" if commit_sha else "") | ||
|
||
|
||
def report_pending(github: Optional["Github"] = None) -> None: | ||
""" | ||
Set the commit benchmark status to pending | ||
""" | ||
if not github: | ||
return | ||
get_commit(github).create_status( | ||
state="pending", description="Running benchmarks", context=GH_STATUS_CONTEXT | ||
) | ||
|
||
|
||
def default_runner(cmd: str, **kwargs: Any) -> "CompletedProcess[bytes]": | ||
""" | ||
Default code runner, interchangeable with invoke context runner | ||
""" | ||
return subprocess.run(cmd, shell=True, check=True, **kwargs) | ||
|
||
|
||
def get_commit_bench_path(commit_sha: str) -> str: | ||
return f"{GH_BENCH_FILE_PATH}/{commit_sha}/result.json" | ||
|
||
|
||
def measure_perf( | ||
github: Optional["Github"], run: Callable[..., Any] = default_runner | ||
) -> None: | ||
""" | ||
Measure benchmark command performance and save results in file | ||
Checks that the benchmark run was stable | ||
Saves the benchmark results to github | ||
""" | ||
run(f"python -m pyperf command -o {BENCH_PERF_FILE} -- {BENCH_COMMAND}") | ||
run(f"python -m pyperf check {BENCH_PERF_FILE}") | ||
if not github: | ||
return | ||
repo = github.get_repo(GH_REPO) | ||
commit_sha = get_req_env("COMMIT_SHA") | ||
with open(BENCH_PERF_FILE, "r", encoding="utf-8") as bench_file: | ||
try: | ||
repo.create_file( | ||
path=get_commit_bench_path(commit_sha), | ||
message=f"build: benchmark run {commit_sha[:7]}", | ||
content=bench_file.read(), | ||
branch=GH_BENCH_BRANCH, | ||
) | ||
except GithubException: | ||
print("Unable to save benchmark results to repo") | ||
|
||
|
||
def fetch_branch_bench_json(github: "Github", branch: str) -> Optional[str]: | ||
""" | ||
Retrieve the benchmark results for the head commit of the given branch | ||
""" | ||
repo = github.get_repo(GH_REPO) | ||
commit_sha = repo.get_branch(branch).commit.sha | ||
commit_bench_path = get_commit_bench_path(commit_sha) | ||
try: | ||
content_file = repo.get_contents(commit_bench_path, GH_BENCH_BRANCH) | ||
if isinstance(content_file, list): | ||
raise Exception | ||
return str(content_file.decoded_content.decode()) | ||
except (UnknownObjectException, Exception): | ||
print("Unable to retrieve benchmark results from repo") | ||
return None | ||
|
||
|
||
def fetch_ref_bench_json(github: "Github", ref_branch: str = GH_BRANCH_REF) -> bool: | ||
""" | ||
Retrieve and save the benchmark results on the reference branch | ||
Skipping the current branch is the reference branch | ||
""" | ||
if get_branch() == ref_branch: | ||
return False | ||
|
||
ref_json = fetch_branch_bench_json(github, ref_branch) | ||
if not ref_json: | ||
return False | ||
|
||
with open(BENCH_REF_FILE, "w", encoding="utf-8") as ref_json_file: | ||
ref_json_file.write(ref_json) | ||
return True | ||
|
||
|
||
def compare_bench_status( | ||
perf_file: str = BENCH_PERF_FILE, ref_file: str = BENCH_REF_FILE | ||
) -> Tuple[str, bool]: | ||
""" | ||
Compare benchmarks for current branch to reference and return results | ||
indicating success or failure and the github status description | ||
""" | ||
cmd = f"python -m pyperf compare_to -q {ref_file} {perf_file}" | ||
return default_runner(cmd, stdout=subprocess.PIPE).stdout.decode().strip(), True | ||
|
||
|
||
def get_bench_status(bench_file: str = BENCH_PERF_FILE) -> Tuple[str, bool]: | ||
""" | ||
Get the status of the benchmark file indicating success or failure | ||
and the github status description | ||
""" | ||
cmd = f"python -m pyperf show -q {bench_file}" | ||
return default_runner(cmd, stdout=subprocess.PIPE).stdout.decode().strip(), True | ||
|
||
|
||
def report_status(github: Optional["Github"] = None) -> None: | ||
""" | ||
Report benchmark run results to github as the commit status | ||
""" | ||
if not github: | ||
return | ||
|
||
if fetch_ref_bench_json(github): | ||
description, success = compare_bench_status() | ||
else: | ||
description, success = get_bench_status() | ||
|
||
get_commit(github).create_status( | ||
state="success" if success else "failure", | ||
target_url=get_target_url(), | ||
description=description, | ||
context=GH_STATUS_CONTEXT, | ||
) | ||
|
||
|
||
def report_error(github: Optional["Github"] = None) -> None: | ||
""" | ||
Report benchmark error to github as the commit status | ||
""" | ||
if not github: | ||
return | ||
get_commit(github).create_status( | ||
state="error", | ||
description="Unable to report benchmark", | ||
context=GH_STATUS_CONTEXT, | ||
) | ||
|
||
|
||
def main(report: bool = False) -> None: | ||
github = Github(get_req_env("GH_TOKEN")) if report else None | ||
try: | ||
report_pending(github) | ||
measure_perf(github) | ||
report_status(github) | ||
except Exception: | ||
report_error(github) | ||
Oops, something went wrong.