Skip to content
Open
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
80 changes: 62 additions & 18 deletions server.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import argparse
import collections
import dataclasses
import json
import logging
Expand All @@ -15,13 +16,13 @@
import time
from metrics import MetricsHandler


from prometheus_client import generate_latest


load_dotenv()

app = FastAPI()
pending_commits = collections.defaultdict(set)


app.add_middleware(
Expand Down Expand Up @@ -49,6 +50,7 @@ class RepoToWatch:
name: str
branch: str
path: str
actions_need_to_pass: bool = False


@dataclasses.dataclass
Expand Down Expand Up @@ -173,35 +175,45 @@ 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")

@app.post("/webhook")
async def github_webhook(request: Request):
MetricsHandler.last_smee_request_timestamp.set(time.time())
payload_body = await request.body()
payload = json.loads(payload_body)

event_header = request.headers.get("X-GitHub-Event")
# check if this is a push event
if event_header != "push":
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"X-GitHub-Event header was not set to push, got value {event_header}"
"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]
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}")
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],))
Expand All @@ -210,6 +222,38 @@ async def github_webhook(request: Request):
return {"status": "webhook received"}



@app.post("/webhook")
async def github_webhook(request: Request):
MetricsHandler.last_smee_request_timestamp.set(time.time())
payload_body = await request.body()
payload = json.loads(payload_body)
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"}

if event_header == "push":
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"
}

elif event_header == "workflow_run":
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also maybe this should get moved to its own function, where we pass in payload and repo_name and branch?

Suggested change
elif event_header == "workflow_run":
if event_header == "workflow_run":
handle_workflow_run(...)

handle_workflow_run(payload, repo_name)

else:
return {
"status": f"X-GitHub-Event header was not set to a valid event, got value {event_header}"
}

@app.get("/metrics")
def get_metrics():
return Response(
Expand All @@ -222,12 +266,11 @@ def get_metrics():
def read_root():
return {"message": "SCE CICD Server"}


def start_smee():
try:
# sends the smee command to the tmux session named smee
# "npx",
smee_cmd = [
"npx",
"smee",
"--url",
os.getenv("SMEE_URL"),
Expand All @@ -237,6 +280,7 @@ def start_smee():

process = subprocess.Popen(
smee_cmd,
shell=True
)
logger.info(f"smee started with PID {process.pid}")
except Exception:
Expand Down