From 2727753752ffef3bb0021e8025dada76dcb43b5a Mon Sep 17 00:00:00 2001 From: Emily Date: Fri, 2 Jan 2026 17:56:21 -0800 Subject: [PATCH 1/8] creating cicd actions step --- server.py | 1 + 1 file changed, 1 insertion(+) diff --git a/server.py b/server.py index b0366d4..bd5051f 100644 --- a/server.py +++ b/server.py @@ -179,6 +179,7 @@ async def github_webhook(request: Request): MetricsHandler.last_smee_request_timestamp.set(time.time()) payload_body = await request.body() payload = json.loads(payload_body) + print("Payload:", payload) # simpler event_header = request.headers.get("X-GitHub-Event") # check if this is a push event From c9af6ded541f1977656f7c743ff99dd404465ee0 Mon Sep 17 00:00:00 2001 From: Emily Date: Fri, 2 Jan 2026 21:56:31 -0800 Subject: [PATCH 2/8] testing plan 4 --- server.py | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/server.py b/server.py index bd5051f..75765ea 100644 --- a/server.py +++ b/server.py @@ -49,6 +49,7 @@ class RepoToWatch: name: str branch: str path: str + actions_need_to_pass: bool = False @dataclasses.dataclass @@ -182,22 +183,36 @@ async def github_webhook(request: Request): print("Payload:", payload) # simpler event_header = request.headers.get("X-GitHub-Event") - # check if this is a push event - if event_header != "push": + + # check if commit on branch passed actions based on type of event + actions_need_to_pass = False + if event_header == "push": + ref = payload.get("ref", "") + branch = ref.split("/")[-1] + elif event_header == "workflow_run": + workflow_run = payload.get("workflow_run", {}) + status = workflow_run.get("status") + conclusion = workflow_run.get("conclusion") + branch = workflow_run.get("head_branch") + + if status == "completed" and conclusion == "success": + actions_need_to_pass = True + else: + return { + "status": f"Committed changes did not pass requirements. Status: {status}" + } + else: return { - "status": f"X-GitHub-Event header was not set to push, got value {event_header}" + "status": f"X-GitHub-Event header was not set to a valid event, got value {event_header}" } - - ref = payload.get("ref", "") - branch = ref.split("/")[-1] + repo_name = payload.get("repository", {}).get("name") - key = (repo_name, branch) if args.development and key not in config: # if we are in development mode, pretend that # we wanted to watch this repo no matter what - config[key] = RepoToWatch(name=repo_name, branch=branch, path="/dev/null") + config[key] = RepoToWatch(name=repo_name, branch=branch, path="/dev/null", actions_need_to_pass=actions_need_to_pass) if key not in config: logging.warning(f"not acting on repo and branch name of {key}") @@ -223,6 +238,8 @@ def get_metrics(): def read_root(): return {"message": "SCE CICD Server"} +def check_actions_passed(): + pass def start_smee(): try: From 72c4ca39c725537bfd1b84bf6dbb59749be9905f Mon Sep 17 00:00:00 2001 From: Emily Date: Fri, 2 Jan 2026 23:07:29 -0800 Subject: [PATCH 3/8] only do the repo update if the commit on said branch passed actions --- server.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/server.py b/server.py index 75765ea..f29f72c 100644 --- a/server.py +++ b/server.py @@ -238,9 +238,6 @@ def get_metrics(): def read_root(): return {"message": "SCE CICD Server"} -def check_actions_passed(): - pass - def start_smee(): try: # sends the smee command to the tmux session named smee From b851c7de46ffff009f899087030a258d5cae5a16 Mon Sep 17 00:00:00 2001 From: Emily Date: Sat, 3 Jan 2026 20:54:46 -0800 Subject: [PATCH 4/8] removed printing payload --- server.py | 1 - 1 file changed, 1 deletion(-) diff --git a/server.py b/server.py index f29f72c..91f6c07 100644 --- a/server.py +++ b/server.py @@ -180,7 +180,6 @@ async def github_webhook(request: Request): MetricsHandler.last_smee_request_timestamp.set(time.time()) payload_body = await request.body() payload = json.loads(payload_body) - print("Payload:", payload) # simpler event_header = request.headers.get("X-GitHub-Event") From e30d86b108b2c4298c37a0aba584c3386c568666 Mon Sep 17 00:00:00 2001 From: Emily Date: Tue, 6 Jan 2026 15:35:28 -0800 Subject: [PATCH 5/8] testing, not done yet --- server.py | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/server.py b/server.py index 91f6c07..a7325ef 100644 --- a/server.py +++ b/server.py @@ -14,9 +14,10 @@ import requests import time from metrics import MetricsHandler - +from collections import defaultdict from prometheus_client import generate_latest +pending_commits = defaultdict(set) load_dotenv() @@ -180,23 +181,32 @@ async def github_webhook(request: Request): MetricsHandler.last_smee_request_timestamp.set(time.time()) payload_body = await request.body() payload = json.loads(payload_body) - + head_sha = payload.get("head_sha") event_header = request.headers.get("X-GitHub-Event") - - # check if commit on branch passed actions based on type of event + actions_need_to_pass = False + repo_name = payload.get("repository", {}).get("name") if event_header == "push": - ref = payload.get("ref", "") - branch = ref.split("/")[-1] + pending_commits[repo_name].add(head_sha) + logger.info(f"Stored {head_sha} for {repo_name}") + return { + "status": f"commit recorded" + } elif event_header == "workflow_run": workflow_run = payload.get("workflow_run", {}) status = workflow_run.get("status") conclusion = workflow_run.get("conclusion") - branch = workflow_run.get("head_branch") + head_sha = payload.get("head_sha", {}).get("id") - if status == "completed" and conclusion == "success": - actions_need_to_pass = True - else: + if not head_sha or not repo_name: + return {"status": "missing head_sha or repo name"} + + if head_sha not in pending_commits: + return { + "status": f"Not in pending_commits" + } + + if status != "completed" or conclusion != "success": return { "status": f"Committed changes did not pass requirements. Status: {status}" } @@ -204,8 +214,12 @@ async def github_webhook(request: Request): return { "status": f"X-GitHub-Event header was not set to a valid event, got value {event_header}" } + + actions_need_to_pass = True + pending_commits[repo_name].discard(head_sha) - repo_name = payload.get("repository", {}).get("name") + ref = payload.get("ref", "") + branch = ref.split("/")[-1] key = (repo_name, branch) if args.development and key not in config: From c063e718abf95c59bfec741524e9f663b1e1b0a3 Mon Sep 17 00:00:00 2001 From: Emily Date: Tue, 6 Jan 2026 17:21:32 -0800 Subject: [PATCH 6/8] checked for head_commit --- server.py | 79 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 44 insertions(+), 35 deletions(-) diff --git a/server.py b/server.py index a7325ef..553f3fa 100644 --- a/server.py +++ b/server.py @@ -181,14 +181,20 @@ async def github_webhook(request: Request): MetricsHandler.last_smee_request_timestamp.set(time.time()) payload_body = await request.body() payload = json.loads(payload_body) - head_sha = payload.get("head_sha") event_header = request.headers.get("X-GitHub-Event") - - actions_need_to_pass = False repo_name = payload.get("repository", {}).get("name") + actions_need_to_pass = False + + if (not repo_name): + return {"status": "missing repo name"} + if event_header == "push": - pending_commits[repo_name].add(head_sha) - logger.info(f"Stored {head_sha} for {repo_name}") + head_commit = payload.get("head_commit", {}).get("id") + if not head_commit: + return {"status": "missing head_commit"} + pending_commits[repo_name].add(head_commit) + logger.info(f"Stored {head_commit} for {repo_name}") + return { "status": f"commit recorded" } @@ -196,12 +202,10 @@ async def github_webhook(request: Request): workflow_run = payload.get("workflow_run", {}) status = workflow_run.get("status") conclusion = workflow_run.get("conclusion") - head_sha = payload.get("head_sha", {}).get("id") - - if not head_sha or not repo_name: - return {"status": "missing head_sha or repo name"} - - if head_sha not in pending_commits: + head_commit = workflow_run.get("head_commit", {}).get("id") + branch = workflow_run.get("head_branch") + + if head_commit not in pending_commits.get(repo_name, set()): return { "status": f"Not in pending_commits" } @@ -210,35 +214,40 @@ async def github_webhook(request: Request): return { "status": f"Committed changes did not pass requirements. Status: {status}" } + + actions_need_to_pass = True + commits = pending_commits.get(repo_name) + if commits: + pending_commits[repo_name].discard(head_commit) + + # check for any empty repos + if not commits: + pending_commits.pop(repo_name) + + ref = payload.get("ref", "") + branch = ref.split("/")[-1] + key = (repo_name, branch) + + if args.development and key not in config: + # if we are in development mode, pretend that + # we wanted to watch this repo no matter what + config[key] = RepoToWatch(name=repo_name, branch=branch, path="/dev/null", actions_need_to_pass=actions_need_to_pass) + + if key not in config: + logging.warning(f"not acting on repo and branch name of {key}") + return {"status": f"not acting on repo and branch name of {key}"} + + logger.info(f"Push to {branch} detected for {repo_name}") + # update the repo + thread = threading.Thread(target=update_repo, args=(config[key],)) + thread.start() + + return {"status": "webhook received"} else: return { "status": f"X-GitHub-Event header was not set to a valid event, got value {event_header}" } - actions_need_to_pass = True - pending_commits[repo_name].discard(head_sha) - - ref = payload.get("ref", "") - branch = ref.split("/")[-1] - key = (repo_name, branch) - - if args.development and key not in config: - # if we are in development mode, pretend that - # we wanted to watch this repo no matter what - config[key] = RepoToWatch(name=repo_name, branch=branch, path="/dev/null", actions_need_to_pass=actions_need_to_pass) - - if key not in config: - logging.warning(f"not acting on repo and branch name of {key}") - return {"status": f"not acting on repo and branch name of {key}"} - - logger.info(f"Push to {branch} detected for {repo_name}") - # update the repo - thread = threading.Thread(target=update_repo, args=(config[key],)) - thread.start() - - return {"status": "webhook received"} - - @app.get("/metrics") def get_metrics(): return Response( From 0a36fa1fad6aef68a77e96c6b579b03c55809c75 Mon Sep 17 00:00:00 2001 From: Emily Date: Thu, 8 Jan 2026 10:50:09 -0800 Subject: [PATCH 7/8] created handle_workflow_run function --- server.py | 94 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 50 insertions(+), 44 deletions(-) diff --git a/server.py b/server.py index 553f3fa..2eede23 100644 --- a/server.py +++ b/server.py @@ -175,6 +175,53 @@ def update_repo(repo_config: RepoToWatch) -> RepoUpdateResult: except Exception: logger.exception("update_repo had a bad time") +def handle_workflow_run(payload, repo_name): + workflow_run = payload.get("workflow_run", {}) + status = workflow_run.get("status") + conclusion = workflow_run.get("conclusion") + head_commit = workflow_run.get("head_commit", {}).get("id") + branch = workflow_run.get("head_branch") + + if head_commit not in pending_commits.get(repo_name, set()): + return { + "status": f"Not in pending_commits" + } + + if status != "completed" or conclusion != "success": + return { + "status": f"Committed changes did not pass requirements. Status: {status}" + } + + actions_need_to_pass = True + commits = pending_commits.get(repo_name) + if commits: + pending_commits[repo_name].discard(head_commit) + + # check for any empty repos + if not commits: + pending_commits.pop(repo_name) + + ref = payload.get("ref", "") + branch = ref.split("/")[-1] + key = (repo_name, branch) + + if args.development and key not in config: + # if we are in development mode, pretend that + # we wanted to watch this repo no matter what + config[key] = RepoToWatch(name=repo_name, branch=branch, path="/dev/null", actions_need_to_pass=actions_need_to_pass) + + if key not in config: + logging.warning(f"not acting on repo and branch name of {key}") + return {"status": f"not acting on repo and branch name of {key}"} + + logger.info(f"Push to {branch} detected for {repo_name}") + # update the repo + thread = threading.Thread(target=update_repo, args=(config[key],)) + thread.start() + + return {"status": "webhook received"} + + @app.post("/webhook") async def github_webhook(request: Request): @@ -184,7 +231,7 @@ async def github_webhook(request: Request): event_header = request.headers.get("X-GitHub-Event") repo_name = payload.get("repository", {}).get("name") actions_need_to_pass = False - + if (not repo_name): return {"status": "missing repo name"} @@ -198,51 +245,10 @@ async def github_webhook(request: Request): return { "status": f"commit recorded" } + elif event_header == "workflow_run": - workflow_run = payload.get("workflow_run", {}) - status = workflow_run.get("status") - conclusion = workflow_run.get("conclusion") - head_commit = workflow_run.get("head_commit", {}).get("id") - branch = workflow_run.get("head_branch") - - if head_commit not in pending_commits.get(repo_name, set()): - return { - "status": f"Not in pending_commits" - } + handle_workflow_run(payload, repo_name) - if status != "completed" or conclusion != "success": - return { - "status": f"Committed changes did not pass requirements. Status: {status}" - } - - actions_need_to_pass = True - commits = pending_commits.get(repo_name) - if commits: - pending_commits[repo_name].discard(head_commit) - - # check for any empty repos - if not commits: - pending_commits.pop(repo_name) - - ref = payload.get("ref", "") - branch = ref.split("/")[-1] - key = (repo_name, branch) - - if args.development and key not in config: - # if we are in development mode, pretend that - # we wanted to watch this repo no matter what - config[key] = RepoToWatch(name=repo_name, branch=branch, path="/dev/null", actions_need_to_pass=actions_need_to_pass) - - if key not in config: - logging.warning(f"not acting on repo and branch name of {key}") - return {"status": f"not acting on repo and branch name of {key}"} - - logger.info(f"Push to {branch} detected for {repo_name}") - # update the repo - thread = threading.Thread(target=update_repo, args=(config[key],)) - thread.start() - - return {"status": "webhook received"} else: return { "status": f"X-GitHub-Event header was not set to a valid event, got value {event_header}" From 472500b699ea2b49bdc7aa06a4d82da4e771c3f3 Mon Sep 17 00:00:00 2001 From: Emily Date: Sat, 10 Jan 2026 11:02:44 -0800 Subject: [PATCH 8/8] test --- server.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/server.py b/server.py index 2eede23..653ddbd 100644 --- a/server.py +++ b/server.py @@ -1,4 +1,5 @@ import argparse +import collections import dataclasses import json import logging @@ -14,15 +15,14 @@ import requests import time from metrics import MetricsHandler -from collections import defaultdict from prometheus_client import generate_latest -pending_commits = defaultdict(set) load_dotenv() app = FastAPI() +pending_commits = collections.defaultdict(set) app.add_middleware( @@ -269,8 +269,8 @@ def read_root(): def start_smee(): try: # sends the smee command to the tmux session named smee + # "npx", smee_cmd = [ - "npx", "smee", "--url", os.getenv("SMEE_URL"), @@ -280,6 +280,7 @@ def start_smee(): process = subprocess.Popen( smee_cmd, + shell=True ) logger.info(f"smee started with PID {process.pid}") except Exception: