Skip to content

Commit

Permalink
wip fetch pending
Browse files Browse the repository at this point in the history
Signed-off-by: Jakub Kicinski <[email protected]>
  • Loading branch information
kuba-moo committed Nov 30, 2023
1 parent c025f3d commit 74ea9e5
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 6 deletions.
9 changes: 7 additions & 2 deletions pw/patchwork.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,14 +151,19 @@ def get_project(self, name):
def get_projects_all(self):
return self.get_all('projects')

def get_patches_all(self, delegate=None, project=None, since=None):
def get_patches_all(self, delegate=None, project=None, since=None, action_required=None):
if project is None:
project = self._project
query = {'project': project }
query = {'project': project}
if delegate:
query['delegate'] = delegate
if since:
query['since'] = since
# Hack up "action required" as patchwork doesn't have actual filter for it
# we assume states 1 and 2 are action required ('New' and 'Under Review')
if action_required:
query['state'] = '1&state=2'
query['archived'] = 'false'
return self.get_all('patches', query)

def get_series_all(self, project=None, since=None):
Expand Down
92 changes: 88 additions & 4 deletions trivial-net-brancher.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
"""
Config:
[filters]
ignore_delegate=bpf
gate_checks=build_clang,build_32bit,build_allmodconfig_warn
[trees]
net-next=net-next, net-next, origin, origin/main
[target]
Expand All @@ -27,14 +30,85 @@
"""


ignore_delegate = {}
gate_checks = {}


def hour_timestamp(when=None) -> int:
if when is None:
when = datetime.datetime.now(datetime.UTC)
ts = when.timestamp()
return int(ts / (60 * 60))


def create_new(config, state, tree, tgt_remote) -> None:
def pwe_has_all_checks(pw, entry) -> bool:
if "checks" not in entry:
return False
checks = pw.request(entry["checks"])
found = 0
for c in checks:
if c["context"] in gate_checks and c["state"] == "success":
found += 1
return found == len(gate_checks)


def pwe_series_id_or_none(entry) -> int:
if len(entry.get("series", [])) > 0:
return entry["series"][0]["id"]


def pwe_get_pending(pw, config) -> List:
log_open_sec("Loading patches")
things = pw.get_patches_all(action_required=True)
log_end_sec()

log_open_sec("Filter by delegates")
res = []
for entry in things:
delegate = entry.get("delegate", None)
if delegate and delegate["username"] in ignore_delegate:
log(f"Skip because of delegate ({delegate['username']}): " + entry["name"])
else:
res.append(entry)
things = res
log_end_sec()

log_open_sec("Filter by checks")
skip_check_series = set()
res = []
for entry in things:
series_id = pwe_series_id_or_none(entry)
if series_id in skip_check_series:
log("Skip because of failing/missing check elsewhere in the series: " + entry["name"])
elif not pwe_has_all_checks(pw, entry):
log("Skip because of failing/missing check: " + entry["name"])
if series_id:
skip_check_series.add(series_id)
else:
res.append(entry)
things = res
log_end_sec()

log_open_sec("Filter by checks by other patches in the series")
res = []
for entry in things:
if pwe_series_id_or_none(entry) in skip_check_series:
log("Skip because of failing check elsewhere in the series: " + entry["name"])
else:
res.append(entry)
things = res
log_end_sec()

return things


def apply_pending_patches(pw, config, tree) -> None:
log_open_sec("Get pending submissions from patchwork")
things = pwe_get_pending(pw, config)
log_end_sec()


def create_new(pw, config, state, tree, tgt_remote) -> None:
now = datetime.datetime.now(datetime.UTC)
pfx = config.get("target", "branch_pfx")
branch_name = pfx + datetime.datetime.now(datetime.UTC).strftime("%Y-%m-%d--%H-%M")
Expand All @@ -51,6 +125,8 @@ def create_new(config, state, tree, tgt_remote) -> None:
tree.git_pull(url)
log_end_sec()

apply_pending_patches(pw, config, tree)

state["branches"][branch_name] = now.isoformat()

log_open_sec("Pushing out")
Expand Down Expand Up @@ -107,7 +183,7 @@ def dump_branches(config, state) -> None:
log_end_sec()


def main_loop(config, state, tree, tgt_remote) -> None:
def main_loop(pw, config, state, tree, tgt_remote) -> None:
now = datetime.datetime.now(datetime.UTC)
now_h = hour_timestamp(now)
freq = int(config.get("target", "freq"))
Expand All @@ -116,7 +192,7 @@ def main_loop(config, state, tree, tgt_remote) -> None:
return

reap_old(config, state, tree, tgt_remote)
create_new(config, state, tree, tgt_remote)
create_new(pw, config, state, tree, tgt_remote)

state["last"] = now_h

Expand Down Expand Up @@ -152,6 +228,8 @@ def main() -> None:
log_init(config.get('log', 'type', fallback='stdout'),
config.get('log', 'file', fallback=None))

pw = Patchwork(config)

state = {}
if os.path.exists("brancher.state"):
with open("brancher.state") as fp:
Expand All @@ -162,6 +240,12 @@ def main() -> None:
if "branches" not in state:
state["branches"] = {}

# Parse global config
global ignore_delegate
ignore_delegate = set(config.get('filters', 'ignore_delegate', fallback="").split(','))
global gate_checks
gate_checks = set(config.get('filters', 'gate_checks', fallback="").split(','))

tree_obj = None
tree_dir = config.get('dirs', 'trees', fallback=os.path.join(NIPA_DIR, "../"))
for tree in config['trees']:
Expand All @@ -179,7 +263,7 @@ def main() -> None:

try:
while True:
main_loop(config, state, tree, tgt_remote)
main_loop(pw, config, state, tree, tgt_remote)
finally:
with open('brancher.state', 'w') as f:
json.dump(state, f)
Expand Down

0 comments on commit 74ea9e5

Please sign in to comment.