Skip to content
Merged
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
54 changes: 33 additions & 21 deletions caching/check.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
we want to only cache on a "pass" or "fail" status as these mean that Tuxsuite
actually completed its work and didnt timeout.
"""

import argparse
import json
import os
Expand All @@ -48,7 +49,11 @@
# pylint: disable-next=import-error
import requests

from utils import get_patches_hash, get_workflow_name_to_var_name, update_repository_variable
from utils import (
get_patches_hash,
get_workflow_name_to_var_name,
update_repository_variable,
)

OWNER = "ClangBuiltLinux"
REPO = "continuous-integration2"
Expand All @@ -63,8 +68,7 @@
TIMEOUT = 64


class MalformedCacheError(Exception):
...
class MalformedCacheError(Exception): ...


def parse_args():
Expand Down Expand Up @@ -107,17 +111,16 @@ def ___purge___cache___():
list_response = requests.get(list_url, headers=headers, timeout=TIMEOUT)
print(list_response.content)
all_variables_keys = [
x["name"] for x in json.loads(list_response.content)["variables"]
x["name"]
for x in json.loads(list_response.content)["variables"]
if x["name"].startswith("_")
]

for key in all_variables_keys:
delete_url = (
f"https://api.github.com/repos/{OWNER}/{REPO}/actions/variables/{key}"
)
delete_response = requests.delete(delete_url,
headers=headers,
timeout=TIMEOUT)
delete_response = requests.delete(delete_url, headers=headers, timeout=TIMEOUT)
if delete_response.status_code != 204:
print(f"ERROR: Couldn't delete cache entry with key {key}")
sys.exit(1)
Expand Down Expand Up @@ -154,16 +157,19 @@ def get_repository_variable_or_none(name: str) -> Optional[dict]:
return json.loads(as_dict["value"])


def create_repository_variable(name: str, linux_sha: str, clang_version: str,
patches_hash: str) -> None:
def create_repository_variable(
name: str, linux_sha: str, clang_version: str, patches_hash: str
) -> None:
_url = f"https://api.github.com/repos/{OWNER}/{REPO}/actions/variables"

_value = json.dumps({
"linux_sha": linux_sha,
"clang_version": clang_version,
"patches_hash": patches_hash,
"build_status": "presuite",
})
_value = json.dumps(
{
"linux_sha": linux_sha,
"clang_version": clang_version,
"patches_hash": patches_hash,
"build_status": "presuite",
}
)
data = {"name": name, "value": _value}

resp = requests.post(_url, headers=headers, json=data, timeout=TIMEOUT)
Expand Down Expand Up @@ -199,8 +205,10 @@ def create_repository_variable(name: str, linux_sha: str, clang_version: str,
# pull down repo variable
result = get_repository_variable_or_none(VAR_NAME)
if result is None:
print(f"CACHE MISS: Did not find repo variable {VAR_NAME} "
f"from workflow_name: {args.workflow_name}. Creating it now.")
print(
f"CACHE MISS: Did not find repo variable {VAR_NAME} "
f"from workflow_name: {args.workflow_name}. Creating it now."
)
create_repository_variable(
VAR_NAME,
linux_sha=curr_sha,
Expand All @@ -219,14 +227,19 @@ def create_repository_variable(name: str, linux_sha: str, clang_version: str,
raise MalformedCacheError(
f"The cache with key {VAR_NAME} based on workflow '{args.workflow_name}' "
f"is one or more fields. It's missing: {missing_fields}\n"
f"The current cache looks as follows:\n{result}.")
f"The current cache looks as follows:\n{result}."
)

cached_sha = result["linux_sha"]
cached_clang_version = result["clang_version"]
cached_build_status = result["build_status"]
cached_patches_hash = result.get("patches_hash", curr_patches_hash)

if cached_sha != curr_sha or cached_clang_version != curr_clang_version or cached_patches_hash != curr_patches_hash:
if (
cached_sha != curr_sha
or cached_clang_version != curr_clang_version
or cached_patches_hash != curr_patches_hash
):
print(f"""\
CACHE MISS: current linux_sha is {curr_sha}, clang_version is {curr_clang_version},
and current patches_hash is {curr_patches_hash} while {args.workflow_name} has
Expand Down Expand Up @@ -271,5 +284,4 @@ def create_repository_variable(name: str, linux_sha: str, clang_version: str,
with open(env_file, "a", encoding="utf-8") as fd:
fd.write(f"CACHE_PASS={cached_build_status.strip()}")

sys.exit(
0) # signifies to the workflow that no jobs should run ('success')
sys.exit(0) # signifies to the workflow that no jobs should run ('success')
34 changes: 17 additions & 17 deletions caching/update.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,11 @@
import urllib.request
from pathlib import Path

from utils import get_patches_hash, get_workflow_name_to_var_name, update_repository_variable
from utils import (
get_patches_hash,
get_workflow_name_to_var_name,
update_repository_variable,
)

if "GITHUB_WORKFLOW" not in os.environ:
print("Couldn't find GITHUB_WORKFLOW in env. Not in a GitHub Workflow?")
Expand All @@ -38,15 +42,12 @@
MOCK = "MOCK" in os.environ


def update_cache(status: str, git_sha: str, clang_version: str,
patches_hash: str):
def update_cache(status: str, git_sha: str, clang_version: str, patches_hash: str):
print(f"Trying to update cache with status: {status}")
cache_entry_key = get_workflow_name_to_var_name(
os.environ["GITHUB_WORKFLOW"])
cache_entry_key = get_workflow_name_to_var_name(os.environ["GITHUB_WORKFLOW"])

if "REPO_SCOPED_PAT" not in os.environ:
print(
"Couldn't find REPO_SCOPED_PAT in env. Not in a GitHub Workflow?")
print("Couldn't find REPO_SCOPED_PAT in env. Not in a GitHub Workflow?")
sys.exit(1)

headers = {"Authorization": f"Bearer {os.environ['REPO_SCOPED_PAT']}"}
Expand Down Expand Up @@ -82,8 +83,7 @@ def main():
for entry, build in builds.items():
try:
git_sha = build["git_sha"]
clang_version = build["tuxmake_metadata"]["compiler"][
"version_full"]
clang_version = build["tuxmake_metadata"]["compiler"]["version_full"]
break
except KeyError:
builds_that_are_missing_metadata.append(entry)
Expand All @@ -100,32 +100,32 @@ def main():
build_log_raw = response.read().decode()

failed_pattern = (
r"(?<=Apply patch set FAILED\s)[0-9A-Za-z._:/\-\s]*?(?=\serror: )")
r"(?<=Apply patch set FAILED\s)[0-9A-Za-z._:/\-\s]*?(?=\serror: )"
)
failed_matches = re.findall(failed_pattern, build_log_raw)
if len(failed_matches) == 0:
print(
f"No patches failed to apply yet the build status stated there were: {build['status_message']}"
)
sys.exit(
0) # Not sure how we got here but continue the action anyways
sys.exit(0) # Not sure how we got here but continue the action anyways

patches_that_failed_to_apply = failed_matches[0].split('\n')
print(
f"Error: Some patches failed to apply.\n{patches_that_failed_to_apply}\n"
)
print(f"Error: Some patches failed to apply.\n{patches_that_failed_to_apply}\n")
sys.exit(1)

if len(builds_that_are_missing_metadata) == len(builds):
raise RuntimeError(
f"Could not find a suitable git sha or compiler version in any build\n"
f"Here's the build.json:\n{raw}")
f"Here's the build.json:\n{raw}"
)

if len(builds_that_are_missing_metadata) > 0:
print(
"Warning: Some of the builds in builds.json are malformed and missing "
"some metadata.\n"
f"Here's a list: {builds_that_are_missing_metadata}\n"
f"Here's the build.json in question:\n{raw}")
f"Here's the build.json in question:\n{raw}"
)

assert git_sha and clang_version

Expand Down
42 changes: 23 additions & 19 deletions generator/generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,34 +17,36 @@


def parse_args(trees):
parser = ArgumentParser(
description='Generate yml files and perform extra checks')
parser = ArgumentParser(description='Generate yml files and perform extra checks')

parser.add_argument('-c',
'--check',
action='store_true',
help='Fail if generating yml files results in a diff')
parser.add_argument(
'-c',
'--check',
action='store_true',
help='Fail if generating yml files results in a diff',
)
parser.add_argument(
'trees',
choices=[*trees, 'all'],
default='all',
help='The trees to generate yml files for (default: all)',
metavar='TREES',
nargs='*')
nargs='*',
)

return parser.parse_args()


def update_llvm_tot_version():
# Avoids pulling in an extra Python package dependency
curl_cmd = [
'curl', '-fLSs',
'https://raw.githubusercontent.com/llvm/llvm-project/main/cmake/Modules/LLVMVersion.cmake'
'curl',
'-fLSs',
'https://raw.githubusercontent.com/llvm/llvm-project/main/cmake/Modules/LLVMVersion.cmake',
]
cmakelists = subprocess.run(curl_cmd,
capture_output=True,
check=True,
text=True).stdout
cmakelists = subprocess.run(
curl_cmd, capture_output=True, check=True, text=True
).stdout

if not (match := re.search(r'set\(LLVM_VERSION_MAJOR (\d+)', cmakelists)):
raise RuntimeError('Could not find LLVM_VERSION_MAJOR?')
Expand All @@ -64,21 +66,23 @@ def generate(config, tree):

def check(trees_arg):
try:
subprocess.run(['git', 'rev-parse', '--git-dir'],
check=True,
capture_output=True)
subprocess.run(
['git', 'rev-parse', '--git-dir'], check=True, capture_output=True
)
except subprocess.CalledProcessError:
# Print a nicer error message versus spewing the exception
print('Script is not being run inside a git repository!')
sys.exit(1)

if subprocess.run(
['git', '--no-optional-locks', 'status', '-uno', '--porcelain'],
capture_output=True,
check=True).stdout:
capture_output=True,
check=True,
).stdout:
print(
f"\nRunning 'generate.py {trees_arg}' generated the following diff:\n",
flush=True)
flush=True,
)
subprocess.run(['git', '--no-pager', 'diff', 'HEAD'], check=True)
print(
"\nPlease run 'generate.py all' locally then commit and push the changes it creates!"
Expand Down
Loading
Loading