-
Notifications
You must be signed in to change notification settings - Fork 91
/
github.rb
110 lines (90 loc) · 3.24 KB
/
github.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# frozen_string_literal: true
class CloverWeb
hash_branch(:webhook_prefix, "github") do |r|
r.post true do
body = r.body.read
unless check_signature(r.headers["x-hub-signature-256"], body)
response.status = 401
r.halt
end
response.headers["Content-Type"] = "application/json"
data = JSON.parse(body)
case r.headers["x-github-event"]
when "installation"
return handle_installation(data)
when "workflow_job"
return handle_workflow_job(data)
end
return error("Unhandled event")
end
end
def error(msg)
{error: {message: msg}}.to_json
end
def success(msg)
{message: msg}.to_json
end
def check_signature(signature, body)
return false unless signature
method, actual_digest = signature.split("=")
expected_digest = OpenSSL::HMAC.hexdigest(method, Config.github_app_webhook_secret, body)
Rack::Utils.secure_compare(actual_digest, expected_digest)
end
def handle_installation(data)
installation = GithubInstallation[installation_id: data["installation"]["id"]]
case data["action"]
when "deleted"
unless installation
return error("Unregistered installation")
end
installation.runners.each(&:incr_destroy)
installation.repositories.each(&:incr_destroy)
installation.destroy
Clog.emit("GithubInstallation is deleted.") { {github_installation: {ubid: installation.ubid, type: installation.type}} }
return success("GithubInstallation[#{installation.ubid}] deleted")
end
error("Unhandled installation action")
end
def handle_workflow_job(data)
unless (installation = GithubInstallation[installation_id: data["installation"]["id"]])
return error("Unregistered installation")
end
unless (job = data["workflow_job"])
Clog.emit("No workflow_job in the payload") { {workflow_job_missing: {installation_id: installation.id, action: data["action"]}} }
return error("No workflow_job in the payload")
end
unless (label = job.fetch("labels").find { Github.runner_labels.key?(_1) })
return error("Unmatched label")
end
if data["action"] == "queued"
st = Prog::Vm::GithubRunner.assemble(
installation,
repository_name: data["repository"]["full_name"],
label: label,
default_branch: data["repository"]["default_branch"]
)
runner = GithubRunner[st.id]
return success("GithubRunner[#{runner.ubid}] created")
end
unless (runner_id = job.fetch("runner_id"))
return error("A workflow_job without runner_id")
end
runner = GithubRunner.first(
installation_id: installation.id,
repository_name: data["repository"]["full_name"],
runner_id: runner_id
)
return error("Unregistered runner") unless runner
runner.update(workflow_job: job.except("steps"))
case data["action"]
when "in_progress"
runner.log_duration("runner_started", Time.parse(job["started_at"]) - Time.parse(job["created_at"]))
success("GithubRunner[#{runner.ubid}] picked job #{job.fetch("id")}")
when "completed"
runner.incr_destroy
success("GithubRunner[#{runner.ubid}] deleted")
else
error("Unhandled workflow_job action")
end
end
end