2022-11-29 06:06:59 +00:00
|
|
|
"""
|
|
|
|
These commands are used in the CI pipeline.
|
|
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
import json
|
|
|
|
import logging
|
2022-12-08 07:09:43 +00:00
|
|
|
import os
|
2022-11-29 06:06:59 +00:00
|
|
|
import pathlib
|
2022-12-08 07:09:43 +00:00
|
|
|
import time
|
|
|
|
from typing import TYPE_CHECKING
|
2022-11-29 06:06:59 +00:00
|
|
|
|
|
|
|
from ptscripts import Context, command_group
|
|
|
|
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
REPO_ROOT = pathlib.Path(__file__).parent.parent
|
|
|
|
|
|
|
|
# Define the command group
|
|
|
|
ci = command_group(name="ci", help="CI Related Commands", description=__doc__)
|
|
|
|
|
|
|
|
|
2022-12-08 07:09:43 +00:00
|
|
|
@ci.command(
|
|
|
|
name="process-changed-files",
|
|
|
|
arguments={
|
|
|
|
"event_name": {
|
|
|
|
"help": "The name of the GitHub event being processed.",
|
|
|
|
},
|
|
|
|
"changed_files": {
|
|
|
|
"help": "JSON payload of changed files from the 'dorny/paths-filter' GitHub action.",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
)
|
|
|
|
def process_changed_files(ctx: Context, event_name: str, changed_files: pathlib.Path):
|
|
|
|
"""
|
|
|
|
Set GH Actions outputs for what should build or not.
|
|
|
|
"""
|
|
|
|
gh_event_path = os.environ.get("GITHUB_EVENT_PATH") or None
|
|
|
|
if gh_event_path is None:
|
|
|
|
ctx.warn("The 'GITHUB_EVENT_PATH' variable is not set.")
|
|
|
|
ctx.exit(1)
|
|
|
|
|
|
|
|
if TYPE_CHECKING:
|
|
|
|
assert gh_event_path is not None
|
|
|
|
|
|
|
|
github_output = os.environ.get("GITHUB_OUTPUT")
|
|
|
|
if github_output is None:
|
|
|
|
ctx.warn("The 'GITHUB_OUTPUT' variable is not set.")
|
|
|
|
ctx.exit(1)
|
|
|
|
|
|
|
|
if TYPE_CHECKING:
|
|
|
|
assert github_output is not None
|
|
|
|
|
|
|
|
try:
|
|
|
|
gh_event = json.loads(open(gh_event_path).read())
|
|
|
|
except Exception as exc:
|
|
|
|
ctx.error(f"Could not load the GH Event payload from {gh_event_path!r}:\n", exc)
|
|
|
|
ctx.exit(1)
|
|
|
|
|
|
|
|
ctx.info("GH Event Payload:")
|
|
|
|
ctx.print(gh_event, soft_wrap=True)
|
|
|
|
# Let's it print until the end
|
|
|
|
time.sleep(1)
|
|
|
|
|
|
|
|
if not changed_files.exists():
|
|
|
|
ctx.error(f"The '{changed_files}' file does not exist.")
|
|
|
|
ctx.exit(1)
|
|
|
|
try:
|
|
|
|
changed_files_contents = json.loads(changed_files.read_text())
|
|
|
|
except Exception as exc:
|
|
|
|
ctx.error(f"Could not load the changed files from '{changed_files}': {exc}")
|
|
|
|
ctx.exit(1)
|
|
|
|
|
|
|
|
ctx.info("Sanitizing paths and confirming no path traversal is being used...")
|
|
|
|
sanitized_changed_files = {}
|
|
|
|
for key, data in changed_files_contents.items():
|
|
|
|
try:
|
|
|
|
loaded_data = json.loads(data)
|
|
|
|
except ValueError:
|
|
|
|
loaded_data = data
|
|
|
|
if key.endswith("_files"):
|
|
|
|
files = set()
|
|
|
|
for entry in list(loaded_data):
|
|
|
|
if not entry:
|
|
|
|
loaded_data.remove(entry)
|
|
|
|
try:
|
|
|
|
entry = REPO_ROOT.joinpath(entry).resolve().relative_to(REPO_ROOT)
|
|
|
|
except ValueError:
|
|
|
|
ctx.error(
|
|
|
|
f"While processing the changed files key {key!r}, the "
|
|
|
|
f"path entry {entry!r} was checked and it's not relative "
|
|
|
|
"to the repository root."
|
|
|
|
)
|
|
|
|
ctx.exit(1)
|
|
|
|
files.add(str(entry))
|
|
|
|
sanitized_changed_files[key] = sorted(files)
|
|
|
|
continue
|
|
|
|
sanitized_changed_files[key] = loaded_data
|
|
|
|
|
|
|
|
ctx.info("Writing 'changed-files' to the github outputs file")
|
|
|
|
with open(github_output, "a", encoding="utf-8") as wfh:
|
|
|
|
wfh.write(f"changed-files={json.dumps(sanitized_changed_files)}\n")
|
|
|
|
|
|
|
|
ctx.info("Selecting which type of jobs(self hosted runners or not) to run")
|
|
|
|
jobs = {"github-hosted-runners": False, "self-hosted-runners": False}
|
|
|
|
if event_name == "pull_request":
|
|
|
|
ctx.info("Running from a pull request event")
|
|
|
|
pr_event_data = gh_event["pull_request"]
|
|
|
|
if (
|
|
|
|
pr_event_data["head"]["repo"]["full_name"]
|
|
|
|
== pr_event_data["base"]["repo"]["full_name"]
|
|
|
|
):
|
|
|
|
# If this is a pull request coming from the same repository, don't run anything
|
|
|
|
ctx.info("Pull request is coming from the same repository.")
|
|
|
|
ctx.info("Not running any jobs since they will run against the branch")
|
|
|
|
ctx.info("Writing 'jobs' to the github outputs file")
|
|
|
|
with open(github_output, "a", encoding="utf-8") as wfh:
|
|
|
|
wfh.write(f"jobs={json.dumps(jobs)}\n")
|
|
|
|
ctx.exit(0)
|
|
|
|
|
|
|
|
# This is a PR from a forked repository
|
|
|
|
ctx.info("Pull request is not comming from the same repository")
|
|
|
|
jobs["github-hosted-runners"] = jobs["self-hosted-runners"] = True
|
|
|
|
ctx.info("Writing 'jobs' to the github outputs file")
|
|
|
|
with open(github_output, "a", encoding="utf-8") as wfh:
|
|
|
|
wfh.write(f"jobs={json.dumps(jobs)}\n")
|
|
|
|
ctx.exit(0)
|
|
|
|
|
|
|
|
# This is a push event
|
|
|
|
ctx.info("Running from a push event")
|
|
|
|
if gh_event["repository"]["fork"] is True:
|
|
|
|
# This is running on a forked repository, don't run tests
|
|
|
|
ctx.info("The push event is on a forked repository")
|
|
|
|
jobs["github-hosted-runners"] = True
|
|
|
|
ctx.info("Writing 'jobs' to the github outputs file")
|
|
|
|
with open(github_output, "a", encoding="utf-8") as wfh:
|
|
|
|
wfh.write(f"jobs={json.dumps(jobs)}\n")
|
|
|
|
ctx.exit(0)
|
|
|
|
|
|
|
|
# Not running on a fork, run everything
|
|
|
|
ctx.info("The push event is from the main repository")
|
|
|
|
jobs["github-hosted-runners"] = jobs["self-hosted-runners"] = True
|
|
|
|
ctx.info("Writing 'jobs' to the github outputs file")
|
|
|
|
with open(github_output, "a", encoding="utf-8") as wfh:
|
|
|
|
wfh.write(f"jobs={json.dumps(jobs)}")
|
|
|
|
ctx.exit(0)
|
|
|
|
|
|
|
|
|
2022-11-29 06:06:59 +00:00
|
|
|
@ci.command(
|
|
|
|
arguments={
|
|
|
|
"distro_slug": {
|
|
|
|
"help": "The distribution slug to generate the matrix for",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
)
|
|
|
|
def matrix(ctx: Context, distro_slug: str):
|
|
|
|
"""
|
|
|
|
Generate the test matrix.
|
|
|
|
"""
|
|
|
|
_matrix = []
|
|
|
|
for transport in ("zeromq", "tcp"):
|
|
|
|
if transport == "tcp":
|
|
|
|
if distro_slug not in ("centosstream-9", "ubuntu-22.04-arm64"):
|
|
|
|
# Only run TCP transport tests on these distributions
|
|
|
|
continue
|
|
|
|
for chunk in ("unit", "functional", "integration", "scenarios"):
|
|
|
|
if transport == "tcp" and chunk in ("unit", "functional"):
|
|
|
|
# Only integration and scenarios shall be tested under TCP,
|
|
|
|
# the rest would be repeating tests
|
|
|
|
continue
|
|
|
|
if "macos" in distro_slug and chunk == "scenarios":
|
|
|
|
continue
|
|
|
|
_matrix.append({"transport": transport, "tests-chunk": chunk})
|
|
|
|
print(json.dumps(_matrix))
|
|
|
|
ctx.exit(0)
|
|
|
|
|
|
|
|
|
|
|
|
@ci.command(
|
|
|
|
name="transport-matrix",
|
|
|
|
arguments={
|
|
|
|
"distro_slug": {
|
|
|
|
"help": "The distribution slug to generate the matrix for",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
)
|
|
|
|
def transport_matrix(ctx: Context, distro_slug: str):
|
|
|
|
"""
|
|
|
|
Generate the test matrix.
|
|
|
|
"""
|
|
|
|
_matrix = []
|
|
|
|
for transport in ("zeromq", "tcp"):
|
|
|
|
if transport == "tcp":
|
|
|
|
if distro_slug not in ("centosstream-9", "ubuntu-22.04-arm64"):
|
|
|
|
# Only run TCP transport tests on these distributions
|
|
|
|
continue
|
|
|
|
_matrix.append({"transport": transport})
|
|
|
|
print(json.dumps(_matrix))
|
|
|
|
ctx.exit(0)
|